Compare commits

..

114 Commits

Author SHA1 Message Date
ocornut
6d910d5487 Version 1.92.5 2025-11-20 17:49:52 +01:00
ocornut
26ff93dadc Examples: NULL: fixed msvc project. 2025-11-20 14:51:25 +01:00
ocornut
a484fd2b56 Examples: Win32+OpenGL3: enable DPI awareness. (#9083) 2025-11-20 14:50:08 +01:00
Rokas Kupstys
8ff7f35eec CI: run imgui_test_suite as part of CI build. 2025-11-20 14:35:48 +01:00
Rokas Kupstys
e8448d0494 CI: general update + rename steps. 2025-11-20 14:33:23 +01:00
ocornut
4ab86e1d61 Nav: fixed scoring when using PageUp/PageDown from a focused item which is outside of visible boundaries. (#9079)
We only use ImGuiNavMoveFlags_AlsoScoreVisibleSet when starting point is visible.
2025-11-19 19:01:22 +01:00
ocornut
0faa0dba15 Drag and Drop: rework cancel drag and drop logic to be overridable. (#9071) 2025-11-19 18:26:44 +01:00
ocornut
db6b8e0fb3 Drag and Drop: handling of Escape after UpdateKeyboardInputs(). (#9071) 2025-11-19 18:26:43 +01:00
ocornut
1f16ca5e5c Docs: update ShowUserGuide() + PR guidelines. (#9071) 2025-11-19 18:26:43 +01:00
ocornut
b4a3d423e0 Docs: amend BeginDisabled() comments. (#9082) 2025-11-19 17:06:44 +01:00
achabense
68894d4149 Docs: fixed outdated comment. (#9082) 2025-11-19 17:03:14 +01:00
ocornut
23bd697f05 Drag and Drop: Pressing Escape while carrying a payload automatically cancel the active drag and drop. (#9071) 2025-11-18 19:18:10 +01:00
ocornut
37f9153105 Nav: improved/clarified behavior when requesting PageUp/PageDown from a focused item which is outside of visible boundaries. (#9079) 2025-11-18 18:59:06 +01:00
ocornut
81e01ddebe Nav: reworked PageUp/PageDown to pick same-page top/bottom page based on inner rectangle rather than clipping rectangle. 2025-11-18 18:57:32 +01:00
ocornut
405c802607 Nav: shallow tweaks. 2025-11-18 18:22:36 +01:00
ocornut
91b5256c57 Clipper: fixed an issue when using up/down from an item outside of visible bound and using the clipper. (#9079) 2025-11-18 17:00:01 +01:00
ocornut
6ae32c696a Backends: fixed misc zealous Clang warnings. 2025-11-18 16:34:35 +01:00
ocornut
9afc62d087 InputText: Fixed an assert when using ImGuiInputTextFlags_ReadOnly and making underlying contents shorter while text is selected. (#9069) 2025-11-18 16:20:51 +01:00
ocornut
c3835de38a CI: fixes warning building example_null w/ msvc as DLL 2025-11-17 18:01:51 +01:00
ocornut
52caa2f38a CI: fixes warning building example_null w/ msvc as DLL 2025-11-17 17:50:37 +01:00
ocornut
04af1a3917 CI: fixes warning building example_null w/ mingw 64-bit, as DLL 2025-11-17 17:43:09 +01:00
ocornut
e1f9b8b3a7 CI: fixes warning building example_null w/ mingw 64-bit, as DLL 2025-11-17 16:49:34 +01:00
ocornut
cfb48969af Examples: CI: backtrack and make example_null embed backend: simpler for all sorts of quick build scripts. 2025-11-17 16:38:07 +01:00
ocornut
0cf5b93a0a CI, Backends: fixes for example_null building. Add consistent IMGUI_IMPL_API in backend. 2025-11-17 16:18:12 +01:00
ocornut
d99baf332c CI: fixes for example_null building. 2025-11-17 16:11:05 +01:00
ocornut
7e919a543c Examples: fix example_null Makefile.
Amend b885382,eb19a77
2025-11-17 15:58:12 +01:00
ocornut
eb19a77848 Examples: fix example_null Makefile.
Amend b885382
2025-11-17 15:52:32 +01:00
ocornut
b885382a63 Backends: Null: added imgui_impl_null platform/renderer backend. 2025-11-17 15:28:03 +01:00
ocornut
9e15ebb402 Backends: GLFW: fixed last ImGui_ImplGlfw_Shutdown() call not immediately clearing the context map. (#9075, #8676, #8239, #8069)
Amend/fix f633a6058
2025-11-17 13:38:17 +01:00
ocornut
f145b0cffd Debug Tools: ID Stack Tool: refactor, extract data/code into ImGuiDebugItemPathQuery for reuse. 2025-11-13 18:32:43 +01:00
ocornut
c254db7637 Debug Tools: ID Stack Tool: store ResultsComplete and don't display incomplete paths. 2025-11-13 16:19:27 +01:00
ocornut
5a0c67c4b8 Debug Tools: ID Stack Tool: extracted code into a StackToolGetResultAsPath() function. 2025-11-13 16:15:00 +01:00
ocornut
ec6219752d Fonts: calling ImFontAtlas::Clear() mid-frame without re-adding a font will lead to a more explicit crash. (#9067)
+ reformat Changelog.
2025-11-13 15:54:50 +01:00
ocornut
d246850787 Fonts: added comment about the classic AddFontFromMemoryTTF() issue. (#9067, #6916, #6781, #5330, #4307, #2042, #2029, #1734, #1259, #220) 2025-11-13 15:42:19 +01:00
ocornut
e60e5bff63 Misc: standardized casing of keyboard mods in comments and demo ("CTRL" -> "Ctrl"). 2025-11-13 15:24:03 +01:00
ocornut
873fe34b31 Debug Tools: ID Stack Tool: preserve first data type, so user of PushOverrideID() e.g. TreeNode() elements don't get demoted from _String to _ID. 2025-11-13 15:05:16 +01:00
ocornut
e3979c2098 Demo: removing absolute __FILE_ from being emitted by default. (#9033) 2025-11-13 14:23:25 +01:00
ocornut
68a44776bd Misc: tweak conflicting id error tooltip to use a link.
Now that nested tooltips are not hiding each others.
2025-11-13 13:47:45 +01:00
ocornut
613cfaf0b4 Tooltips: made BeginTooltipEx() not hide nested tooltips.
It's not typically possible to nest tooltips since BeginTooltipEx() imply ImGuiWindowFlags_NoInputs + following mouse pos + most tooltips would be triggered on hover. But BeginErrorTooltip() bypass that.
2025-11-13 13:47:45 +01:00
ocornut
de917ebb95 Windows: move auto-fit block into braces for clarify. (no-op) 2025-11-11 21:48:17 +01:00
ocornut
501e0adcdb Windows: CalcWindowAutoFitSize() remove child-specific hack added by 29439bdd27 and made obsolete by 7537ba2b4. (#9060, #1710) 2025-11-11 21:47:15 +01:00
ocornut
a2544f9496 Windows: programmatic auto-sizing on a single axis also apply proper logic. (#9060) 2025-11-11 21:37:21 +01:00
ocornut
b51f6e073c Windows: reorganize auto-fitting code blocks in Begin(), step 2.
Toward #9060
2025-11-11 21:15:43 +01:00
ocornut
52e9d94f93 Windows: reorganize auto-fitting code blocks in Begin(), aimed to have no side-effect, but..
..outer ImGuiWindowFlags_AlwaysAutoResize previously took priority for both axis. New logic per-axis.
Toward #9060
2025-11-11 20:03:31 +01:00
ocornut
fc262355ca Windows: Fixed an issue where repeated calls to SetNextWindowSize() using 0.0f to auto-size would keep marking ini settings as dirty.
+ marking dirty on old io.FontAllowUserScaling Ctrl+Wheel
2025-11-11 19:47:48 +01:00
ocornut
7537ba2b44 Windows: fixed single-axis auto-sizing (via double-clicking a border) to take account of remaining scrollbar on the other axis. (#9060)
Potentially now should apply same logic to the other resizing path also described in #9060
2025-11-10 19:36:16 +01:00
ocornut
86daa8930e Backends, Examples: WebGPU: simplified ifndef (#8381) 2025-11-07 13:24:16 +01:00
ocornut
635eb1d8e9 Added .tmp files. 2025-11-06 18:07:18 +01:00
ocornut
bd0e2036e0 Drag and Drop: added ImGuiDragDropFlags_AcceptDrawAsHovered. (#8632)
Not calling SetHoveredId() in that path, does not seem necessary.
2025-11-06 18:07:18 +01:00
ocornut
b0d3c3a674 Drag and Drop: prev/curr storage for DragDropAcceptFlags. ImGuiDragDropFlags_AcceptNoPreviewTooltip test uses DragDropAcceptFlagsPrev for consistency. (#143)
I don't think this would have materialized as a visible bug.
2025-11-06 17:59:01 +01:00
ocornut
dacd080639 Docs: added link to imgui-module. (#8868( 2025-11-06 17:30:00 +01:00
ocornut
8e2e87d638 (Breaking) Commented out legacy SetItemAllowOverlap() obsoleted in 1.89.7: this never worked right. Use SetNextItemAllowOverlap() _before_ item instead. 2025-11-06 16:29:19 +01:00
ocornut
e389502ffb Amends comments referring to 1.92.X to refer to 1.92.0. FontAllowUserScaling not marked obsolete anymore. 2025-11-06 16:28:59 +01:00
ocornut
1c3a60047c (Breaking) IO: commented out legacy io.ClearInputCharacters() obsoleted in 1.89.8. 2025-11-06 16:28:58 +01:00
ocornut
62162747e7 (Breaking) Keys: commented out legacy names which were obsoleted in 1.89.
ImGuiKey_ModCtrl --> ImGuiMod_Ctrl, ImGuiKey_ModShift --> ImGuiMod_Shift, ImGuiKey_ModAlt --> ImGuiMod_Alt, ImGuiKey_ModSuper --> ImGuiMod_Super.
2025-11-06 16:28:25 +01:00
ocornut
189d8c9d9c (Breaking) Commented out legacy ImGuiChildFlags_Border (#462), ImGuiWindowFlags_NavFlattened (#7687), ImGuiWindowFlags_AlwaysUseWindowPadding. 2025-11-06 16:11:07 +01:00
ocornut
f45adb995c Drag and Drop, Style: added basic styling options to DragDrop target rect. Amends. (#9056) 2025-11-06 15:38:20 +01:00
aaronkirkham
7954d6782e Drag and Drop, Style: added basic styling options to DragDrop target rect. (#9056) 2025-11-06 15:34:40 +01:00
Clownacy
59db6ceeb1 Backends: GLFW: lower minimum requirement from GLFW 3.1 to GLFW 3.0. (#9055) 2025-11-06 15:25:11 +01:00
ocornut
a0bfbe4d8f Windows: BgClickFlags inherited by default + missing info in Changelog. Amend 40f9e4e. (#899, #3071, #5044, #3379) 2025-11-05 20:16:45 +01:00
ocornut
e674f57bb6 Backends: SDL3: Fixed an issue with missing characters events when an already active text field changes viewports. (#9054)
Always use SDL_GetKeyboardFocus().
(tried to defer ImGui_ImplSDL3_PlatformSetImeData() processing for when OS-window is available but it didn't actually work because we don't systemetically OS-focus new viewports and SDL3 only sent characters to keyboard focused window.)
2025-11-05 19:15:47 +01:00
ocornut
1897248bda Misc: added assert to detect ~ImGuiContext() called without DestroyContext(). (#9051) 2025-11-04 17:55:18 +01:00
ocornut
051a31594f Metrics: fixed table and columns rect highlight from display when metrics window is not in the same viewport as the table. 2025-11-03 19:48:57 +01:00
ocornut
dc6e0f4b9e Tables: Angled headers: fixed an auto-resize feedback loop that could affect tables with empty non-resizing columns using angled headers. 2025-11-03 19:35:19 +01:00
BrutPitt
df3f2fff88 Examples: WebGPU: moved CreateWGPUSurface to the bottom of the file due to interference with X.h. (#8381) 2025-11-03 19:15:41 +01:00
ocornut
8e5e79054e Examples: WGPU: tweak headers and standardize other things so examples have less differences. (#8381) 2025-11-03 19:05:28 +01:00
BrutPitt
3cc8b470a6 Backends, Examples: WebGPU: header optimization. Added the code for using Dawn “pre-built” library. (#8381) 2025-11-03 19:05:28 +01:00
ocornut
f1becf7e4b Amend 149587b config/build infos change to be resilient to IM_ASSERT() macros using stringification inside a list. 2025-11-03 14:31:14 +01:00
Brenton Bostick
a3546b52f8 Various typo fixes (#9042) 2025-11-03 13:26:12 +01:00
ocornut
823ccc274e Examples: update docs. (#8381) 2025-10-31 19:34:12 +01:00
BrutPitt
ff672b2db3 Examples: SDL2+WebGPU, SDL3+WebGPU: add new examples. (#8381) 2025-10-31 19:10:23 +01:00
BrutPitt
778aed9966 Examples: GLFW+WebGPU: update to latest specs and to work on Emscripten 4.0.10+ and latest Dawn-Native, WGPU-Native. (#8381, #8567, #8191, #7435) 2025-10-31 19:10:23 +01:00
BrutPitt
c5b2a848fa Backends: WebGPU: added smaller and debug helpers. (#8381, #8831, #8567, #8191, #7435) 2025-10-31 19:10:23 +01:00
BrutPitt
d0e3b1d4e2 Backends: WebGPU: added ImGui_ImplWGPU_CreateWGPUSurfaceHelper(). (#8381, #8831, #8567, #8191, #7435) 2025-10-31 19:10:23 +01:00
ocornut
505ff536f9 Textures: fixed an issue preventing multi-contexts from using each others' fonts if context 2 runs after context 1's Render() function. (#9039) 2025-10-31 16:38:27 +01:00
ocornut
db577cd445 Fonts: rename internal fields for consistency. 2025-10-31 16:38:23 +01:00
ocornut
149587b85b Config/build infos emit infos to convey when IM_ASSERT() macro is disabled. 2025-10-30 18:03:36 +01:00
ocornut
670a92723a Move IM_STRINGIFY() to imgui.h 2025-10-30 17:47:06 +01:00
ocornut
130c3e6b75 Backends: Vulkan: tweak comments. (#9041) 2025-10-30 16:04:21 +01:00
ocornut
3c578fa87e InputText: restore truncating, now between UTF-8 codepoint. (#9029)
Amend e612536, 2a194e2.
2025-10-29 18:40:40 +01:00
ocornut
8df962a6ed Debug Tools: fixed DebugTextEncoding() potentially reading out of bounds if provided a trailing truncated UTF-8 sequence. 2025-10-29 17:58:52 +01:00
ocornut
2a194e21a0 InputText: revert truncation behavior from e612536 as it can truncate mid-UTF8. (#9029) 2025-10-29 17:24:23 +01:00
ocornut
9753c741b9 Disabled, ButtonBehavior: fixed a bug when a previously enabled item that got nav focus and then turns disabled could still be activated using keyboard. (#9036)
ButtonBehavior() was relying on lack of nav focus for keyboard handling
2025-10-29 16:43:27 +01:00
ocornut
7c483a0eba Add indentation to ButtonBehavior() - no logic change. 2025-10-29 16:39:37 +01:00
ocornut
0ba9fedf1a Win32: Revert 1.92.4 change of comparing dwPacketNumber. (#8556) 2025-10-29 16:29:47 +01:00
ocornut
2c54b15a5f Update ignore list. 2025-10-29 15:03:55 +01:00
ocornut
2a229c8cb8 Examples: SDL3+OpenGL3: fixed Emscripten makefile + ignore list.
Can't get this to run however.
2025-10-29 14:21:43 +01:00
ocornut
40f9e4e8e2 Windows: store BgClickFlags which allows the equivalent of io.ConfigWindowsMoveFromTitleBarOnly to be overridden on a per window basis. (#899, #3071, #5044, + #3379)
io.ConfigWindowsMoveFromTitleBarOnly now sets initial value for BgClickFlags. Using e.g. ImGui::GetCurrentWindow()->BgClickFlags &= ~ImGuiWindowBgClickFlags_Move; allow per-window override.
This will be extended for supporting scrolling options for #3379.
As a minor side effect: the effect of enabling io.ConfigWindowsMoveFromTitleBarOnly now happens one frame later ('window_modal_bounds_exceeding_work_area" test accidentally broke in some situations because of that)
2025-10-28 19:13:11 +01:00
ocornut
245e12cca7 Internals: tweak UpdateMouseMovingWindowEndFrame(). 2025-10-28 19:06:37 +01:00
ocornut
8019d39545 Shuffle a few internal context fields to reduce padding. 2025-10-28 19:06:36 +01:00
ocornut
a1632c6116 InputText, Demo: amend comments to direct more users to the std::string version.
https://www.youtube.com/watch?v=pLwvNdpTpjs wasted a solid hour before finding this.
Crazy that people are using AI instead of actually _reading_ comments, demo and headers. (The information appeared multiple times on their screen)
2025-10-24 17:10:57 +02:00
ocornut
c72d0b2cbb Backends: Vulkan: SwapChainImageUsage assume VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT which is added automatically. (#8946, #8110, #8111, #8686)
Merge bad3c14 which was accidentally only pushed to docking. No important side effect.
2025-10-23 21:04:48 +02:00
ocornut
e6125361f9 InputText: paste does a truncate when not fitting instead of ignoring it. (#9029) 2025-10-23 20:53:29 +02:00
ocornut
b7e45b3a48 InputText: rework STB_TEXTEDIT_INSERTCHARS() signature to allow partial insertion (unused). (#9029)
To be submitted as a PR to nothings/stb.
2025-10-23 20:19:16 +02:00
ocornut
6add99f8d2 Examples: SDL3+Vulkan: Fixed call to ImGui_ImplVulkanH_CreateOrResizeWindow() during resize. (#9030)
Surprisingly it still worked because ImGui_ImplVulkanH_CreateWindowSwapChain() pulls from `cap.currentExtent` when available.
2025-10-23 20:00:57 +02:00
ocornut
750c5d2a61 InputText: do not require anymore that CursorPos be clamped by user code. (#9029)
Add clamping outside of callback code + simplify logic. The previous logic checking for difference was because old code e.g. 21d03edcb0 required a ImTextCountCharsFromUtf8() which is not required since #7925.
2025-10-23 18:54:32 +02:00
ocornut
e571ccf3f4 InputText: removed unnecessary variables. 2025-10-23 18:43:20 +02:00
ocornut
b8573a7e33 Groups: fixed an issue reporting IsItemEdited() signal after EndGroup() for some widgets e.g. Checkbox(), Selectable(). (#9028) 2025-10-23 13:54:14 +02:00
ocornut
bc5da9b367 Examples: DirectX10: Amends. (#8979) 2025-10-22 13:58:51 +02:00
ocornut
b3dab0a406 Examples: DirectX10, DirectX11, DirectX12: comments about fullscreen mode and swapchain setup. (#8979) 2025-10-22 13:57:27 +02:00
ocornut
2a022d997b Examples: GLFW+WebGPU: removed unnecessary ImGui_ImplWGPU_InvalidateDeviceObjects() call during surface resize. (#8381)
+ Relayout changelog.
2025-10-22 13:42:23 +02:00
ocornut
5870b979a8 Examples: GLFW+WebGPU: fixed cmakefile for example to use legacy path. (#8381)
Amend 71447b94f
2025-10-22 13:39:00 +02:00
ocornut
bdb8243602 Backends: SDl3: Fixed Platform_OpenInShellFn() return value. (#9027) 2025-10-22 13:33:36 +02:00
ocornut
b46f099a3f Backends: GLFW: fixed building on Linux platforms where Wayland headers are not available. (#9024, #8969, #8921, #8920) 2025-10-20 23:57:09 +02:00
ocornut
63bfad401f MultiSelect: added ImGuiMultiSelectFlags_NoSelectOnRightClick. (#8200, #9015) 2025-10-20 18:58:45 +02:00
Ingmar Rieger
e11b7a0414 Make ClearPlatformHandlers and ClearRendererHandlers API public (#9016) 2025-10-18 17:34:40 +02:00
mwlasiuk
065f9e0269 Backends: Vulkan: added IMGUI_IMPL_VULKAN_VOLK_FILENAME. (#9008, #7722, #6582, #4854) 2025-10-16 20:36:30 +02:00
ocornut
4b1f5aba80 Examples: GLFW+WebGPU: moving blocks to simplify upcoming diff. (#8381) 2025-10-16 19:42:28 +02:00
ocornut
71447b94fb Examples: GLFW+WebGPU: default build to legacy for now. (#8381) 2025-10-16 18:23:02 +02:00
BrutPitt
3dc511c71d Backends: WebGPU: update to compile with Dawn and Emscripten's 4.0.10+ '--use-port=emdawnwebgpu' ports. (#8381, #8898) 2025-10-16 18:16:28 +02:00
ocornut
36de604a5b InputText: avoid continuously overwriting ownership of ImGuiKey_Enter / ImGuiKey_KeypadEnter in order to allow e.g. external Shortcut to override behavior. (#9004) 2025-10-16 16:12:40 +02:00
ocornut
2a5e9a15e4 InputTextMultiline: fixed a crash when using ImGuiInputTextFlags_WordWrap and resizing the parent window while keeping the multi-line field active. (#9007, #3237) 2025-10-15 19:12:40 +02:00
ocornut
d7fec5e1d3 Tables: fixed a bug where nesting BeginTable()->Begin()->BeginTable(). (#9005) 2025-10-15 16:50:11 +02:00
ocornut
7d8d587bc0 Version 1.92.5 WIP 2025-10-15 16:46:18 +02:00
60 changed files with 4653 additions and 1021 deletions

View File

@@ -2,7 +2,9 @@
1. PLEASE CAREFULLY READ: [Contributing Guidelines](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md)
2. Make sure you're using a special branch just for this pull request. (Sometimes people unknowingly use a default branch, then later update that branch, which updates the pull request with the other changes if it hasn't been merged yet.)
2. **Make sure you're using a special branch just for this pull request**. (In git, 1 PR = 1 branch. If you update the branch the PR will be updated.)
3. Clear this template before submitting your PR.
3. Consider running the [imgui_test_suite](https://github.com/ocornut/imgui_test_engine) or adding new tests to test for expected behaviors.
4. Clear this template before submitting your PR.

View File

@@ -16,13 +16,21 @@ on:
- requested
jobs:
Windows:
Build-Windows:
runs-on: windows-2025
name: Build - Windows
defaults:
run:
working-directory: ${{ github.workspace }}/imgui
env:
VS_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\
MSBUILD_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
path: ${{ github.workspace }}/imgui
# The VulkanSDK libs for Windows is manually generated using build_windows_vulkan_libs.ps1 + attached to issue #8925.
# (we have a .yml workflow in commit history if it becomes ever useful to create this on CI too)
@@ -61,7 +69,7 @@ jobs:
echo '#define IMGUI_IMPLEMENTATION' >> example_single_file.cpp
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
g++ -I. -Wall -Wformat -shared -o libimgui.dll -Wl,--out-implib,libimgui.a example_single_file.cpp -limm32
g++ -I. -Wall -Wformat -DIMGUI_API='__declspec(dllimport)' -o example_null.exe examples/example_null/main.cpp -L. -limgui
g++ -I. -Wall -Wformat -DIMGUI_API='__declspec(dllimport)' -DIMGUI_IMPL_API= -o example_null.exe examples/example_null/main.cpp -L. -limgui
rm -f example_null.exe libimgui.* example_single_file.*
- name: Build example_null (extra warnings, msvc 64-bit)
@@ -106,7 +114,7 @@ jobs:
echo #include "misc/single_file/imgui_single_file.h" >> example_single_file.cpp
cl.exe /D_USRDLL /D_WINDLL /I. example_single_file.cpp /LD /FeImGui.dll /link
cl.exe /DIMGUI_API=__declspec(dllimport) /I. ImGui.lib /Feexample_null.exe examples/example_null/main.cpp
cl.exe /DIMGUI_API=__declspec(dllimport) -DIMGUI_IMPL_API= /I. ImGui.lib /Feexample_null.exe examples/example_null/main.cpp
# Win64 examples are more frequently compilted than the Win32 examples.
# More of the Win32 examples requires 'workflow_run' to reduce waste.
@@ -257,10 +265,18 @@ jobs:
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx12/example_win32_directx12.vcxproj /p:Platform=x64 /p:Configuration=Release'
Linux:
Build-Linux:
runs-on: ubuntu-latest
name: Build - Linux
defaults:
run:
working-directory: ${{ github.workspace }}/imgui
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
path: ${{ github.workspace }}/imgui
- name: Install Dependencies
run: |
@@ -474,10 +490,18 @@ jobs:
- name: Build with IMGUI_IMPL_VULKAN_NO_PROTOTYPES
run: g++ -c -I. -std=c++11 -DIMGUI_IMPL_VULKAN_NO_PROTOTYPES=1 backends/imgui_impl_vulkan.cpp
MacOS:
Build-MacOS:
runs-on: macos-latest
name: Build - MacOS
defaults:
run:
working-directory: ${{ github.workspace }}/imgui
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
path: ${{ github.workspace }}/imgui
- name: Install Dependencies
run: |
@@ -548,20 +572,24 @@ jobs:
- name: Build example_apple_opengl2
run: xcodebuild -project examples/example_apple_opengl2/example_apple_opengl2.xcodeproj -target example_osx_opengl2
iOS:
Build-iOS:
runs-on: macos-14
name: Build - iOS
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Build example_apple_metal
run: |
# Code signing is required, but we disable it because it is irrelevant for CI builds.
xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_ios CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
Emscripten:
Build-Emscripten:
runs-on: ubuntu-latest
name: Build - Emscripten
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Install Dependencies
run: |
@@ -599,12 +627,148 @@ jobs:
emcmake cmake -B build -DCMAKE_BUILD_TYPE=Release examples/example_glfw_wgpu
cmake --build build
Android:
Build-Android:
runs-on: ubuntu-latest
name: Build - Android
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Build example_android_opengl3
run: |
cd examples/example_android_opengl3/android
gradle assembleDebug --stacktrace
Test-Windows:
runs-on: windows-2025
name: Test - Windows
defaults:
run:
working-directory: ${{ github.workspace }}/imgui
env:
MSBUILD_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\
steps:
- uses: actions/checkout@v5
with:
path: ${{ github.workspace }}/imgui
- uses: actions/checkout@v5
continue-on-error: true
with:
fetch-depth: 1
repository: ocornut/imgui_test_engine
path: ${{ github.workspace }}/imgui_test_engine
submodules: true
- name: Fix Tests Projects
shell: powershell
working-directory: ${{ github.workspace }}/imgui_test_engine
run: |
# WARNING: This will need updating if toolset/sdk change in project files!
gci -recurse -filter "*.vcxproj" | ForEach-Object {
# Fix SDK and toolset for most samples.
(Get-Content $_.FullName) -Replace "<PlatformToolset>v110</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.20348.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
# Fix SDK and toolset for samples that require newer SDK/toolset. At the moment it is only dx12.
(Get-Content $_.FullName) -Replace "<PlatformToolset>v140</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.20348.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
}
- name: Build Tests
shell: cmd
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
run: '"%MSBUILD_PATH%\MSBuild.exe" imgui_test_suite.vcxproj /p:Platform=x64 /p:Configuration=Release /p:ClFlags=/WX -maxcpucount:%NUMBER_OF_PROCESSORS%'
- name: Run Tests
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
run: Release/imgui_test_suite.exe -nogui -nopause -v2 -ve4 tests
- name: Check for Docking
id: check_docking
shell: bash
working-directory: ${{ github.workspace }}/imgui
run: echo "has_dock=$(grep -q "#define IMGUI_HAS_DOCK" imgui.h && echo true || echo false)" >> $GITHUB_OUTPUT
- name: Run Viewport Tests
if: steps.check_docking.outputs.has_dock == 'true'
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
run: Release/imgui_test_suite.exe -nogui -nopause -v2 -ve4 -viewport-mock viewport
Test-Linux:
runs-on: ubuntu-latest
name: Test - Linux
defaults:
run:
working-directory: ${{ github.workspace }}/imgui
steps:
- uses: actions/checkout@v5
with:
path: ${{ github.workspace }}/imgui
- uses: actions/checkout@v5
with:
fetch-depth: 1
repository: ocornut/imgui_test_engine
path: ${{ github.workspace }}/imgui_test_engine
submodules: true
- name: Build Tests
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
run: make -j$(nproc)
- name: Run Tests
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
run: ./imgui_test_suite -nogui -nopause -v2 -ve4 tests
- name: Check for Docking
id: check_docking
working-directory: ${{ github.workspace }}/imgui
run: echo "has_dock=$(grep -q "#define IMGUI_HAS_DOCK" imgui.h && echo true || echo false)" >> $GITHUB_OUTPUT
- name: Run Viewport Tests
if: steps.check_docking.outputs.has_dock == 'true'
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
run: ./imgui_test_suite -nogui -nopause -v2 -ve4 -viewport-mock viewport
Test-MacOS:
runs-on: macos-latest
name: Test - MacOS
defaults:
run:
working-directory: ${{ github.workspace }}/imgui
steps:
- uses: actions/checkout@v5
with:
path: ${{ github.workspace }}/imgui
- uses: actions/checkout@v5
with:
fetch-depth: 1
repository: ocornut/imgui_test_engine
path: ${{ github.workspace }}/imgui_test_engine
submodules: true
- name: Build Tests
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
run: make -j$(nproc)
- name: Run Tests
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
run: ./imgui_test_suite -nogui -nopause -v2 -ve4 tests
- name: Check for Docking
id: check_docking
working-directory: ${{ github.workspace }}/imgui
run: echo "has_dock=$(grep -q "#define IMGUI_HAS_DOCK" imgui.h && echo true || echo false)" >> $GITHUB_OUTPUT
- name: Run Viewport Tests
if: steps.check_docking.outputs.has_dock == 'true'
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
run: ./imgui_test_suite -nogui -nopause -v2 -ve4 -viewport-mock viewport

4
.gitignore vendored
View File

@@ -12,6 +12,7 @@ imgui*.ini
examples/*/Debug/*
examples/*/Release/*
examples/*/x64/*
examples/*.tmp
## Visual Studio artifacts
.vs
@@ -46,6 +47,9 @@ examples/example_glfw_opengl3/web/*
examples/example_glfw_wgpu/web/*
examples/example_glfw_wgpu/external/*
examples/example_sdl2_opengl3/web/*
examples/example_sdl2_wgpu/web/*
examples/example_sdl3_opengl3/web/*
examples/example_sdl3_wgpu/web/*
## JetBrains IDE artifacts
.idea

View File

@@ -44,7 +44,7 @@ struct ImGui_ImplDX12_InitInfo
D3D12_GPU_DESCRIPTOR_HANDLE LegacySingleSrvGpuDescriptor;
#endif
ImGui_ImplDX12_InitInfo() { memset((void*)this, 0, sizeof(*this)); }
ImGui_ImplDX12_InitInfo() { memset(this, 0, sizeof(*this)); }
};
// Follow "Getting Started" link and check examples/ folder to learn about using backends!

View File

@@ -1,14 +1,14 @@
// dear imgui: Platform Backend for GLFW
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
// (Requires: GLFW 3.1+. Prefer GLFW 3.3+ or GLFW 3.4+ for full feature support.)
// (Requires: GLFW 3.0+. Prefer GLFW 3.3+/3.4+ for full feature support.)
// Implemented features:
// [X] Platform: Clipboard support.
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors) with GLFW 3.1+. Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Multiple Dear ImGui contexts support.
// Missing features or Issues:
// [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
@@ -29,6 +29,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-11-06: Lower minimum requirement to GLFW 3.0. Though a recent version e.g GLFW 3.4 is highly recommended.
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
// 2025-09-15: Content Scales are always reported as 1.0 on Wayland. FramebufferScale are always reported as 1.0 on X11. (#8920, #8921)
// 2025-07-08: Made ImGui_ImplGlfw_GetContentScaleForWindow(), ImGui_ImplGlfw_GetContentScaleForMonitor() helpers return 1.0f on Emscripten and Android platforms, matching macOS logic. (#8742, #8733)
@@ -100,8 +101,10 @@
// Clang warnings with -Weverything
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning: declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
#pragma clang diagnostic ignored "-Wglobal-constructors" // warning: declaration requires a global destructor // similar to above, not sure what the exact difference is.
#endif
// GLFW
@@ -126,9 +129,6 @@
#ifndef GLFW_EXPOSE_NATIVE_X11 // for glfwGetX11Display(), glfwGetX11Window() on Freedesktop (Linux, BSD, etc.)
#define GLFW_EXPOSE_NATIVE_X11
#endif
#ifndef GLFW_EXPOSE_NATIVE_WAYLAND
#define GLFW_EXPOSE_NATIVE_WAYLAND
#endif
#include <GLFW/glfw3native.h>
#endif
#undef Status // X11 headers are leaking this.
@@ -155,6 +155,7 @@
#else
#define GLFW_HAS_NEW_CURSORS (0)
#endif
#define GLFW_HAS_CREATECURSOR (GLFW_VERSION_COMBINED >= 3100) // 3.1+ glfwCreateCursor()
#define GLFW_HAS_GAMEPAD_API (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetGamepadState() new api
#define GLFW_HAS_GETKEYNAME (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwGetKeyName()
#define GLFW_HAS_GETERROR (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetError()
@@ -167,7 +168,7 @@
struct ImGui_ImplGlfw_WindowToContext { GLFWwindow* Window; ImGuiContext* Context; };
static ImVector<ImGui_ImplGlfw_WindowToContext> g_ContextMap;
static void ImGui_ImplGlfw_ContextMap_Add(GLFWwindow* window, ImGuiContext* ctx) { g_ContextMap.push_back(ImGui_ImplGlfw_WindowToContext{ window, ctx }); }
static void ImGui_ImplGlfw_ContextMap_Remove(GLFWwindow* window) { for (ImGui_ImplGlfw_WindowToContext& entry : g_ContextMap) if (entry.Window == window) { g_ContextMap.erase_unsorted(&entry); return; } }
static void ImGui_ImplGlfw_ContextMap_Remove(GLFWwindow* window) { for (ImGui_ImplGlfw_WindowToContext& entry : g_ContextMap) if (entry.Window == window) { g_ContextMap.erase_unsorted(&entry); if (g_ContextMap.empty()) g_ContextMap.clear(); return; } }
static ImGuiContext* ImGui_ImplGlfw_ContextMap_Get(GLFWwindow* window) { for (ImGui_ImplGlfw_WindowToContext& entry : g_ContextMap) if (entry.Window == window) return entry.Context; return nullptr; }
enum GlfwClientApi
@@ -185,7 +186,9 @@ struct ImGui_ImplGlfw_Data
GlfwClientApi ClientApi;
double Time;
GLFWwindow* MouseWindow;
#if GLFW_HAS_CREATECURSOR
GLFWcursor* MouseCursors[ImGuiMouseCursor_COUNT];
#endif
ImVec2 LastValidMousePos;
bool IsWayland;
bool InstalledCallbacks;
@@ -656,7 +659,9 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_glfw (%d)", GLFW_VERSION_COMBINED);
io.BackendPlatformUserData = (void*)bd;
io.BackendPlatformName = bd->BackendPlatformName;
#if GLFW_HAS_CREATECURSOR
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
#endif
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
bd->Context = ImGui::GetCurrentContext();
@@ -682,6 +687,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
// (By design, on X11 cursors are user configurable and some cursors may be missing. When a cursor doesn't exist,
// GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting.
// Missing cursors will return nullptr and our _UpdateMouseCursor() function will use the Arrow cursor instead.)
#if GLFW_HAS_CREATECURSOR
GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr);
bd->MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
bd->MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
@@ -700,6 +706,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
#endif
glfwSetErrorCallback(prev_error_callback);
#endif
#if GLFW_HAS_GETERROR && !defined(__EMSCRIPTEN__) // Eat errors (see #5908)
(void)glfwGetError(nullptr);
#endif
@@ -778,10 +785,10 @@ void ImGui_ImplGlfw_Shutdown()
if (bd->CanvasSelector)
emscripten_set_wheel_callback(bd->CanvasSelector, nullptr, false, nullptr);
#endif
#if GLFW_HAS_CREATECURSOR
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
glfwDestroyCursor(bd->MouseCursors[cursor_n]);
#endif
// Windows: restore our WndProc hook
#ifdef _WIN32
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
@@ -849,7 +856,9 @@ static void ImGui_ImplGlfw_UpdateMouseCursor()
{
// Show OS mouse cursor
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
#if GLFW_HAS_CREATECURSOR
glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
#endif
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
}
@@ -950,8 +959,8 @@ static void ImGui_ImplGlfw_GetWindowSizeAndFramebufferScale(GLFWwindow* window,
int display_w, display_h;
glfwGetWindowSize(window, &w, &h);
glfwGetFramebufferSize(window, &display_w, &display_h);
float fb_scale_x = (w > 0) ? (float)display_w / w : 1.0f;
float fb_scale_y = (h > 0) ? (float)display_h / h : 1.0f;
float fb_scale_x = (w > 0) ? (float)display_w / (float)w : 1.0f;
float fb_scale_y = (h > 0) ? (float)display_h / (float)h : 1.0f;
#if GLFW_HAS_X11_OR_WAYLAND
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
if (!bd->IsWayland)

View File

@@ -7,7 +7,7 @@
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors) with GLFW 3.1+. Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Multiple Dear ImGui contexts support.
// Missing features or Issues:
// [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.

View File

@@ -0,0 +1,102 @@
// dear imgui: Null Platform+Renderer Backends
// This is designed if you need to use a blind Dear Imgui context with no input and no output.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-11-17: Initial version.
#include "imgui.h"
#ifndef IMGUI_DISABLE
#include "imgui_impl_null.h"
// Clang/GCC warnings with -Weverything
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
#endif
IMGUI_IMPL_API bool ImGui_ImplNull_Init()
{
ImGui_ImplNullPlatform_Init();
ImGui_ImplNullRender_Init();
return true;
}
IMGUI_IMPL_API void ImGui_ImplNull_Shutdown()
{
ImGui_ImplNullRender_Shutdown();
ImGui_ImplNullPlatform_Shutdown();
}
IMGUI_IMPL_API void ImGui_ImplNull_NewFrame()
{
ImGui_ImplNullPlatform_NewFrame();
ImGui_ImplNullRender_NewFrame();
}
IMGUI_IMPL_API bool ImGui_ImplNullPlatform_Init()
{
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
return true;
}
IMGUI_IMPL_API void ImGui_ImplNullPlatform_Shutdown()
{
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags &= ~ImGuiBackendFlags_HasMouseCursors;
}
IMGUI_IMPL_API void ImGui_ImplNullPlatform_NewFrame()
{
ImGuiIO& io = ImGui::GetIO();
io.DisplaySize = ImVec2(1920, 1080);
io.DeltaTime = 1.0f / 60.0f;
}
IMGUI_IMPL_API bool ImGui_ImplNullRender_Init()
{
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures;
return true;
}
IMGUI_IMPL_API void ImGui_ImplNullRender_Shutdown()
{
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset;
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasTextures;
}
IMGUI_IMPL_API void ImGui_ImplNullRender_NewFrame()
{
}
static void ImGui_ImplNullRender_UpdateTexture(ImTextureData* tex)
{
if (tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantDestroy)
tex->SetStatus(ImTextureStatus_OK);
if (tex->Status == ImTextureStatus_WantDestroy)
{
tex->SetTexID(ImTextureID_Invalid);
tex->SetStatus(ImTextureStatus_Destroyed);
}
}
IMGUI_IMPL_API void ImGui_ImplNullRender_RenderDrawData(ImDrawData* draw_data)
{
if (draw_data->Textures != nullptr)
for (ImTextureData* tex : *draw_data->Textures)
if (tex->Status != ImTextureStatus_OK)
ImGui_ImplNullRender_UpdateTexture(tex);
}
#endif // #ifndef IMGUI_DISABLE

View File

@@ -0,0 +1,34 @@
// dear imgui: Null Platform+Renderer Backends
// This is designed if you need to use a blind Dear Imgui context with no input and no output.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
#pragma once
#include "imgui.h" // IMGUI_IMPL_API
#ifndef IMGUI_DISABLE
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
// Null = NullPlatform + NullRender
IMGUI_IMPL_API bool ImGui_ImplNull_Init();
IMGUI_IMPL_API void ImGui_ImplNull_Shutdown();
IMGUI_IMPL_API void ImGui_ImplNull_NewFrame();
// Null platform only (single screen, fixed timestep, no inputs)
IMGUI_IMPL_API bool ImGui_ImplNullPlatform_Init();
IMGUI_IMPL_API void ImGui_ImplNullPlatform_Shutdown();
IMGUI_IMPL_API void ImGui_ImplNullPlatform_NewFrame();
// Null renderer only (no output)
IMGUI_IMPL_API bool ImGui_ImplNullRender_Init();
IMGUI_IMPL_API void ImGui_ImplNullRender_Shutdown();
IMGUI_IMPL_API void ImGui_ImplNullRender_NewFrame();
IMGUI_IMPL_API void ImGui_ImplNullRender_RenderDrawData(ImDrawData* draw_data);
#endif // #ifndef IMGUI_DISABLE

View File

@@ -20,6 +20,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-11-05: Fixed an issue with missing characters events when an already active text field changes viewports. (#9054)
// 2025-10-22: Fixed Platform_OpenInShellFn() return value (unused in core).
// 2025-09-24: Skip using the SDL_GetGlobalMouseState() state when one of our window is hovered, as the SDL_EVENT_MOUSE_MOTION data is reliable. Fix macOS notch mouse coordinates issue in fullscreen mode + better perf on X11. (#7919, #7786)
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
// 2025-09-15: Use SDL_GetWindowDisplayScale() on Mac to output DisplayFrameBufferScale. The function is more reliable during resolution changes e.g. going fullscreen. (#8703, #4414)
@@ -111,6 +113,8 @@ struct ImGui_ImplSDL3_Data
// IME handling
SDL_Window* ImeWindow;
ImGuiPlatformImeData ImeData;
bool ImeDirty;
// Mouse handling
Uint32 MouseWindowID;
@@ -138,6 +142,9 @@ static ImGui_ImplSDL3_Data* ImGui_ImplSDL3_GetBackendData()
return ImGui::GetCurrentContext() ? (ImGui_ImplSDL3_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr;
}
// Forward Declarations
static void ImGui_ImplSDL3_UpdateIme();
// Functions
static const char* ImGui_ImplSDL3_GetClipboardText(ImGuiContext*)
{
@@ -153,16 +160,38 @@ static void ImGui_ImplSDL3_SetClipboardText(ImGuiContext*, const char* text)
SDL_SetClipboardText(text);
}
static void ImGui_ImplSDL3_PlatformSetImeData(ImGuiContext*, ImGuiViewport* viewport, ImGuiPlatformImeData* data)
static ImGuiViewport* ImGui_ImplSDL3_GetViewportForWindowID(SDL_WindowID window_id)
{
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
SDL_WindowID window_id = (SDL_WindowID)(intptr_t)viewport->PlatformHandle;
SDL_Window* window = SDL_GetWindowFromID(window_id);
return (window_id == bd->WindowID) ? ImGui::GetMainViewport() : nullptr;
}
static void ImGui_ImplSDL3_PlatformSetImeData(ImGuiContext*, ImGuiViewport*, ImGuiPlatformImeData* data)
{
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
bd->ImeData = *data;
bd->ImeDirty = true;
ImGui_ImplSDL3_UpdateIme();
}
// We discard viewport passed via ImGuiPlatformImeData and always call SDL_StartTextInput() on SDL_GetKeyboardFocus().
static void ImGui_ImplSDL3_UpdateIme()
{
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
ImGuiPlatformImeData* data = &bd->ImeData;
SDL_Window* window = SDL_GetKeyboardFocus();
// Stop previous input
if ((!(data->WantVisible || data->WantTextInput) || bd->ImeWindow != window) && bd->ImeWindow != nullptr)
{
SDL_StopTextInput(bd->ImeWindow);
bd->ImeWindow = nullptr;
}
if ((!bd->ImeDirty && bd->ImeWindow == window) || (window == NULL))
return;
// Start/update current input
bd->ImeDirty = false;
if (data->WantVisible)
{
SDL_Rect r;
@@ -339,13 +368,6 @@ static void ImGui_ImplSDL3_UpdateKeyModifiers(SDL_Keymod sdl_key_mods)
io.AddKeyEvent(ImGuiMod_Super, (sdl_key_mods & SDL_KMOD_GUI) != 0);
}
static ImGuiViewport* ImGui_ImplSDL3_GetViewportForWindowID(SDL_WindowID window_id)
{
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
return (window_id == bd->WindowID) ? ImGui::GetMainViewport() : nullptr;
}
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
@@ -505,7 +527,7 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL3_SetClipboardText;
platform_io.Platform_GetClipboardTextFn = ImGui_ImplSDL3_GetClipboardText;
platform_io.Platform_SetImeDataFn = ImGui_ImplSDL3_PlatformSetImeData;
platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { return SDL_OpenURL(url) == 0; };
platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { return SDL_OpenURL(url); };
// Gamepad handling
bd->GamepadMode = ImGui_ImplSDL3_GamepadMode_AutoFirst;
@@ -797,8 +819,8 @@ static void ImGui_ImplSDL3_GetWindowSizeAndFramebufferScale(SDL_Window* window,
#else
int display_w, display_h;
SDL_GetWindowSizeInPixels(window, &display_w, &display_h);
float fb_scale_x = (w > 0) ? (float)display_w / w : 1.0f;
float fb_scale_y = (h > 0) ? (float)display_h / h : 1.0f;
float fb_scale_x = (w > 0) ? (float)display_w / (float)w : 1.0f;
float fb_scale_y = (h > 0) ? (float)display_h / (float)h : 1.0f;
#endif
if (out_size != nullptr)
@@ -834,6 +856,7 @@ void ImGui_ImplSDL3_NewFrame()
ImGui_ImplSDL3_UpdateMouseData();
ImGui_ImplSDL3_UpdateMouseCursor();
ImGui_ImplSDL3_UpdateIme();
// Update game controllers (if enabled and available)
ImGui_ImplSDL3_UpdateGamepads();

View File

@@ -27,6 +27,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-10-15: Vulkan: Added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to volk.h header. (#9008)
// 2025-09-26: *BREAKING CHANGE*: moved some fields in ImGui_ImplVulkan_InitInfo: init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass, init_info.Subpass --> init_info.PipelineInfoMain.Subpass, init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples, init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo.
// 2025-09-26: *BREAKING CHANGE*: renamed ImGui_ImplVulkan_MainPipelineCreateInfo to ImGui_ImplVulkan_PipelineInfo. Introduced very recently so shouldn't affect many users.
// 2025-09-26: *BREAKING CHANGE*: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a VkImageUsageFlags image_usage` argument, default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT if 0.
@@ -1633,7 +1634,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
info.imageFormat = wd->SurfaceFormat.format;
info.imageColorSpace = wd->SurfaceFormat.colorSpace;
info.imageArrayLayers = 1;
info.imageUsage = (image_usage != 0) ? image_usage : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | image_usage;
info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // Assume that graphics family == present family
info.preTransform = (cap.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : cap.currentTransform;
info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;

View File

@@ -41,9 +41,14 @@
// If you have no idea what this is, leave it alone!
//#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES
// Convenience support for Volk
// [Configuration] Convenience support for Volk
// (you can also technically use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)
// (When using Volk from directory outside your include directories list you can specify full path to the volk.h header,
// for example when using Volk from VulkanSDK and using include_directories(${Vulkan_INCLUDE_DIRS})' from 'find_package(Vulkan REQUIRED)')
//#define IMGUI_IMPL_VULKAN_USE_VOLK
//#define IMGUI_IMPL_VULKAN_VOLK_FILENAME <Volk/volk.h>
//#define IMGUI_IMPL_VULKAN_VOLK_FILENAME <volk.h> // Default
// Reminder: make those changes in your imconfig.h file, not here!
#if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES) && !defined(VK_NO_PROTOTYPES)
#define VK_NO_PROTOTYPES
@@ -54,7 +59,11 @@
// Vulkan includes
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
#ifdef IMGUI_IMPL_VULKAN_VOLK_FILENAME
#include IMGUI_IMPL_VULKAN_VOLK_FILENAME
#else
#include <volk.h>
#endif
#else
#include <vulkan/vulkan.h>
#endif
@@ -84,7 +93,7 @@ struct ImGui_ImplVulkan_PipelineInfo
// and must contain a pool size large enough to hold a small number of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptors.
// - As an convenience, by setting DescriptorPoolSize > 0 the backend will create one for you.
// - About dynamic rendering:
// - When using dynamic rendering, set UseDynamicRendering=true and fill PipelineRenderingCreateInfo structure.
// - When using dynamic rendering, set UseDynamicRendering=true + fill PipelineInfoMain.PipelineRenderingCreateInfo structure.
struct ImGui_ImplVulkan_InitInfo
{
uint32_t ApiVersion; // Fill with API version of Instance, e.g. VK_API_VERSION_1_3 or your value of VkApplicationInfo::apiVersion. May be lower than header version (VK_HEADER_VERSION_COMPLETE)

View File

@@ -1,6 +1,6 @@
// dear imgui: Renderer for WebGPU
// This needs to be used along with a Platform Binding (e.g. GLFW)
// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.)
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL2, SDL3)
// (Please note that WebGPU is a recent API, may not be supported by all browser, and its ecosystem is generally a mess)
// Implemented features:
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID/ImTextureRef!
@@ -8,6 +8,8 @@
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
// [X] Renderer: Texture updates support for dynamic font system (ImGuiBackendFlags_RendererHasTextures).
// Read imgui_impl_wgpu.h about how to use the IMGUI_IMPL_WEBGPU_BACKEND_WGPU or IMGUI_IMPL_WEBGPU_BACKEND_DAWN flags.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// Learn about Dear ImGui:
@@ -18,6 +20,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-10-16: Update to compile with Dawn and Emscripten's 4.0.10+ '--use-port=emdawnwebgpu' ports. (#8381, #8898)
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
// 2025-06-12: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. (#8465)
// 2025-02-26: Recreate image bind groups during render. (#8426, #8046, #7765, #8027) + Update for latest webgpu-native changes.
@@ -46,22 +49,21 @@
#include "imgui.h"
// When targeting native platforms (i.e. NOT Emscripten), one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN
// or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. See imgui_impl_wgpu.h for more details.
#ifndef __EMSCRIPTEN__
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) == defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#error exactly one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be defined!
#endif
#else
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#error neither IMGUI_IMPL_WEBGPU_BACKEND_DAWN nor IMGUI_IMPL_WEBGPU_BACKEND_WGPU may be defined if targeting emscripten!
#endif
#endif
#ifndef IMGUI_DISABLE
#include "imgui_impl_wgpu.h"
#include <limits.h>
#include <webgpu/webgpu.h>
#include <stdio.h>
// One of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. See imgui_impl_wgpu.h for more details.
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) == defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#error Exactly one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be defined!
#endif
// This condition is true when it's built with EMSCRIPTEN using -sUSE_WEBGPU=1 flag (deprecated from 4.0.10)
// This condition is false for all other 3 cases: WGPU-Native, DAWN-Native or DAWN-EMSCRIPTEN (using --use-port=emdawnwebgpu flag)
#if defined(__EMSCRIPTEN__) && defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN
#endif
#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
// Dawn renamed WGPUProgrammableStageDescriptor to WGPUComputeState (see: https://github.com/webgpu-native/webgpu-headers/pull/413)
@@ -259,7 +261,7 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c
{
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
WGPUShaderSourceWGSL wgsl_desc = {};
wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL;
wgsl_desc.code = { wgsl_source, WGPU_STRLEN };
@@ -270,12 +272,12 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c
#endif
WGPUShaderModuleDescriptor desc = {};
desc.nextInChain = reinterpret_cast<WGPUChainedStruct*>(&wgsl_desc);
desc.nextInChain = (WGPUChainedStruct*)&wgsl_desc;
WGPUProgrammableStageDescriptor stage_desc = {};
stage_desc.module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc);
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
stage_desc.entryPoint = { "main", WGPU_STRLEN };
#else
stage_desc.entryPoint = "main";
@@ -398,9 +400,10 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
WGPUBufferDescriptor vb_desc =
{
nullptr,
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
{ "Dear ImGui Vertex buffer", WGPU_STRLEN, },
#else
"Dear ImGui Vertex buffer",
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
WGPU_STRLEN,
#endif
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex,
MEMALIGN(fr->VertexBufferSize * sizeof(ImDrawVert), 4),
@@ -425,9 +428,10 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
WGPUBufferDescriptor ib_desc =
{
nullptr,
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
{ "Dear ImGui Index buffer", WGPU_STRLEN, },
#else
"Dear ImGui Index buffer",
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
WGPU_STRLEN,
#endif
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index,
MEMALIGN(fr->IndexBufferSize * sizeof(ImDrawIdx), 4),
@@ -560,7 +564,7 @@ void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex)
// Create texture
WGPUTextureDescriptor tex_desc = {};
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
tex_desc.label = { "Dear ImGui Texture", WGPU_STRLEN };
#else
tex_desc.label = "Dear ImGui Texture";
@@ -605,7 +609,7 @@ void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex)
// Update full texture or selected blocks. We only ever write to textures regions which have never been used before!
// This backend choose to use tex->UpdateRect but you can use tex->Updates[] to upload individual regions.
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
WGPUTexelCopyTextureInfo dst_view = {};
#else
WGPUImageCopyTexture dst_view = {};
@@ -614,7 +618,7 @@ void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex)
dst_view.mipLevel = 0;
dst_view.origin = { (uint32_t)upload_x, (uint32_t)upload_y, 0 };
dst_view.aspect = WGPUTextureAspect_All;
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
WGPUTexelCopyBufferLayout layout = {};
#else
WGPUTextureDataLayout layout = {};
@@ -636,9 +640,10 @@ static void ImGui_ImplWGPU_CreateUniformBuffer()
WGPUBufferDescriptor ub_desc =
{
nullptr,
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
{ "Dear ImGui Uniform buffer", WGPU_STRLEN, },
#else
"Dear ImGui Uniform buffer",
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
WGPU_STRLEN,
#endif
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform,
MEMALIGN(sizeof(Uniforms), 16),
@@ -751,7 +756,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
// Create depth-stencil State
WGPUDepthStencilState depth_stencil_state = {};
depth_stencil_state.format = bd->depthStencilFormat;
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
depth_stencil_state.depthWriteEnabled = WGPUOptionalBool_False;
#else
depth_stencil_state.depthWriteEnabled = false;
@@ -833,14 +838,18 @@ bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info)
// Setup backend capabilities flags
ImGui_ImplWGPU_Data* bd = IM_NEW(ImGui_ImplWGPU_Data)();
io.BackendRendererUserData = (void*)bd;
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
#if defined(__EMSCRIPTEN__)
io.BackendRendererName = "imgui_impl_webgpu_emscripten";
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
io.BackendRendererName = "imgui_impl_webgpu_dawn";
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
io.BackendRendererName = "imgui_impl_webgpu_wgpu";
io.BackendRendererName = "imgui_impl_wgpu (Dawn, Emscripten)"; // compiled & linked using EMSCRIPTEN with "--use-port=emdawnwebgpu" flag
#else
io.BackendRendererName = "imgui_impl_webgpu";
io.BackendRendererName = "imgui_impl_wgpu (Dawn, Native)";
#endif
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#if defined(__EMSCRIPTEN__)
io.BackendRendererName = "imgui_impl_wgpu (WGPU, Emscripten)"; // linked using EMSCRIPTEN with "-sUSE_WEBGPU=1" flag, deprecated from EMSCRIPTEN 4.0.10
#else
io.BackendRendererName = "imgui_impl_wgpu (WGPU, Native)";
#endif
#endif
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
@@ -905,6 +914,173 @@ void ImGui_ImplWGPU_NewFrame()
IM_ASSERT(0 && "ImGui_ImplWGPU_CreateDeviceObjects() failed!");
}
//-------------------------------------------------------------------------
// Internal Helpers
// Those are currently used by our example applications.
//-------------------------------------------------------------------------
bool ImGui_ImplWGPU_IsSurfaceStatusError(WGPUSurfaceGetCurrentTextureStatus status)
{
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
return (status == WGPUSurfaceGetCurrentTextureStatus_Error);
#else
return (status == WGPUSurfaceGetCurrentTextureStatus_OutOfMemory || status == WGPUSurfaceGetCurrentTextureStatus_DeviceLost);
#endif
}
bool ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(WGPUSurfaceGetCurrentTextureStatus status)
{
#if defined(__EMSCRIPTEN__) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
return (status == WGPUSurfaceGetCurrentTextureStatus_Timeout || status == WGPUSurfaceGetCurrentTextureStatus_Outdated || status == WGPUSurfaceGetCurrentTextureStatus_Lost);
#else
return (status == WGPUSurfaceGetCurrentTextureStatus_Timeout || status == WGPUSurfaceGetCurrentTextureStatus_Outdated || status == WGPUSurfaceGetCurrentTextureStatus_Lost || status == WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal);
#endif
}
// Helpers to obtain a string
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type)
{
switch (type)
{
case WGPUErrorType_Validation: return "Validation";
case WGPUErrorType_OutOfMemory: return "OutOfMemory";
case WGPUErrorType_Unknown: return "Unknown";
case WGPUErrorType_Internal: return "Internal";
default: return "Unknown";
}
}
const char* ImGui_ImplWGPU_GetDeviceLostReasonName(WGPUDeviceLostReason type)
{
switch (type)
{
case WGPUDeviceLostReason_Unknown: return "Unknown";
case WGPUDeviceLostReason_Destroyed: return "Destroyed";
case WGPUDeviceLostReason_CallbackCancelled: return "CallbackCancelled";
case WGPUDeviceLostReason_FailedCreation: return "FailedCreation";
default: return "Unknown";
}
}
#elif !defined(__EMSCRIPTEN__)
const char* ImGui_ImplWGPU_GetLogLevelName(WGPULogLevel level)
{
switch (level)
{
case WGPULogLevel_Error: return "Error";
case WGPULogLevel_Warn: return "Warn";
case WGPULogLevel_Info: return "Info";
case WGPULogLevel_Debug: return "Debug";
case WGPULogLevel_Trace: return "Trace";
default: return "Unknown";
}
}
#endif
const char* ImGui_ImplWGPU_GetBackendTypeName(WGPUBackendType type)
{
switch (type)
{
case WGPUBackendType_WebGPU: return "WebGPU";
case WGPUBackendType_D3D11: return "D3D11";
case WGPUBackendType_D3D12: return "D3D12";
case WGPUBackendType_Metal: return "Metal";
case WGPUBackendType_Vulkan: return "Vulkan";
case WGPUBackendType_OpenGL: return "OpenGL";
case WGPUBackendType_OpenGLES: return "OpenGLES";
default: return "Unknown";
}
}
const char* ImGui_ImplWGPU_GetAdapterTypeName(WGPUAdapterType type)
{
switch (type)
{
case WGPUAdapterType_DiscreteGPU: return "DiscreteGPU";
case WGPUAdapterType_IntegratedGPU: return "IntegratedGPU";
case WGPUAdapterType_CPU: return "CPU";
default: return "Unknown";
}
}
void ImGui_ImplWGPU_DebugPrintAdapterInfo(const WGPUAdapter& adapter)
{
WGPUAdapterInfo info = {};
wgpuAdapterGetInfo(adapter, &info);
printf("description: \"%.*s\"\n", (int)info.description.length, info.description.data);
printf("vendor: \"%.*s\", vendorID: %x\n", (int)info.vendor.length, info.vendor.data, info.vendorID);
printf("architecture: \"%.*s\"\n", (int) info.architecture.length, info.architecture.data);
printf("device: \"%.*s\", deviceID: %x\n", (int)info.device.length, info.device.data, info.deviceID);
printf("backendType: \"%s\"\n", ImGui_ImplWGPU_GetBackendTypeName(info.backendType));
printf("adapterType: \"%s\"\n", ImGui_ImplWGPU_GetAdapterTypeName(info.adapterType));
wgpuAdapterInfoFreeMembers(info);
}
#ifndef __EMSCRIPTEN__
#if defined(__APPLE__)
// MacOS specific: is necessary to compile with "-x objective-c++" flags
// (e.g. using cmake: set_source_files_properties(${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++") )
#include <Cocoa/Cocoa.h>
#include <QuartzCore/CAMetalLayer.h>
#endif
WGPUSurface ImGui_ImplWGPU_CreateWGPUSurfaceHelper(ImGui_ImplWGPU_CreateSurfaceInfo* info)
{
WGPUSurfaceDescriptor surface_descriptor = {};
WGPUSurface surface = {};
#if defined(__APPLE__)
if (strcmp(info->System, "cocoa") == 0)
{
IM_ASSERT(info->RawWindow != nullptr);
NSWindow* ns_window = (NSWindow*)info->RawWindow;
id metal_layer = [CAMetalLayer layer];
[ns_window.contentView setWantsLayer : YES] ;
[ns_window.contentView setLayer : metal_layer] ;
WGPUSurfaceSourceMetalLayer surface_src_metal = {};
surface_src_metal.chain.sType = WGPUSType_SurfaceSourceMetalLayer;
surface_src_metal.layer = metal_layer;
surface_descriptor.nextInChain = &surface_src_metal.chain;
surface = wgpuInstanceCreateSurface(info->Instance, &surface_descriptor);
}
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
if (strcmp(info->System, "wayland") == 0)
{
IM_ASSERT(info->RawDisplay != nullptr && info->RawSurface != nullptr);
WGPUSurfaceSourceWaylandSurface surface_src_wayland = {};
surface_src_wayland.chain.sType = WGPUSType_SurfaceSourceWaylandSurface;
surface_src_wayland.display = info->RawDisplay;
surface_src_wayland.surface = info->RawSurface;
surface_descriptor.nextInChain = &surface_src_wayland.chain;
surface = wgpuInstanceCreateSurface(info->Instance, &surface_descriptor);
}
else if (strcmp(info->System, "x11") == 0)
{
IM_ASSERT(info->RawDisplay != nullptr && info->RawWindow != nullptr);
WGPUSurfaceSourceXlibWindow surface_src_xlib = {};
surface_src_xlib.chain.sType = WGPUSType_SurfaceSourceXlibWindow;
surface_src_xlib.display = info->RawDisplay;
surface_src_xlib.window = (uint64_t)info->RawWindow;
surface_descriptor.nextInChain = &surface_src_xlib.chain;
surface = wgpuInstanceCreateSurface(info->Instance, &surface_descriptor);
}
#elif defined(_WIN32)
if (strcmp(info->System, "win32") == 0)
{
IM_ASSERT(info->RawWindow != nullptr && info->RawInstance != nullptr);
WGPUSurfaceSourceWindowsHWND surface_src_hwnd = {};
surface_src_hwnd.chain.sType = WGPUSType_SurfaceSourceWindowsHWND;
surface_src_hwnd.hinstance = info->RawInstance;
surface_src_hwnd.hwnd = info->RawWindow;
surface_descriptor.nextInChain = &surface_src_hwnd.chain;
surface = wgpuInstanceCreateSurface(info->Instance, &surface_descriptor);
}
#else
#error "Unsupported WebGPU native platform!"
#endif
return surface;
}
#endif // #ifndef __EMSCRIPTEN__
//-----------------------------------------------------------------------------
#endif // #ifndef IMGUI_DISABLE

View File

@@ -1,11 +1,14 @@
// dear imgui: Renderer for WebGPU
// This needs to be used along with a Platform Binding (e.g. GLFW)
// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.)
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL2, SDL3)
// (Please note that WebGPU is a recent API, may not be supported by all browser, and its ecosystem is generally a mess)
// Important note to dawn and/or wgpu users: when targeting native platforms (i.e. NOT emscripten),
// one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided.
// When targeting native platforms:
// - One of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU *must* be provided.
// When targeting Emscripten:
// - We now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN is Emscripten version is 4.0.10+, which correspond to using Emscripten '--use-port=emdawnwebgpu'.
// - We can still define IMGUI_IMPL_WEBGPU_BACKEND_WGPU to use Emscripten '-s USE_WEBGPU=1' which is marked as obsolete by Emscripten.
// Add #define to your imconfig.h file, or as a compilation flag in your build system.
// This requirement will be removed once WebGPU stabilizes and backends converge on a unified interface.
// This requirement may be removed once WebGPU stabilizes and backends converge on a unified interface.
//#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
//#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU
@@ -27,7 +30,20 @@
#include "imgui.h" // IMGUI_IMPL_API
#ifndef IMGUI_DISABLE
// Setup Emscripten default if not specified.
#if defined(__EMSCRIPTEN__) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#include <emscripten/version.h>
#if (__EMSCRIPTEN_major__ >= 4) && (__EMSCRIPTEN_minor__ >= 0) && (__EMSCRIPTEN_tiny__ >= 10)
#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
#else
#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU
#endif
#endif
#include <webgpu/webgpu.h>
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) && !defined(__EMSCRIPTEN__)
#include <webgpu/wgpu.h> // WGPULogLevel
#endif
// Initialization data, for ImGui_ImplWGPU_Init()
struct ImGui_ImplWGPU_InitInfo
@@ -68,4 +84,38 @@ struct ImGui_ImplWGPU_RenderState
WGPURenderPassEncoder RenderPassEncoder;
};
//-------------------------------------------------------------------------
// Internal Helpers
// Those are currently used by our example applications.
//-------------------------------------------------------------------------
// (Optional) Helper to wrap some of the Dawn/WGPU/Emscripten quirks
bool ImGui_ImplWGPU_IsSurfaceStatusError(WGPUSurfaceGetCurrentTextureStatus status);
bool ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(WGPUSurfaceGetCurrentTextureStatus status); // Return whether the texture is suboptimal and may need to be recreated.
// (Optional) Helper for debugging/logging
void ImGui_ImplWGPU_DebugPrintAdapterInfo(const WGPUAdapter& adapter);
const char* ImGui_ImplWGPU_GetBackendTypeName(WGPUBackendType type);
const char* ImGui_ImplWGPU_GetAdapterTypeName(WGPUAdapterType type);
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
const char* ImGui_ImplWGPU_GetDeviceLostReasonName(WGPUDeviceLostReason type);
const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type);
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) && !defined(__EMSCRIPTEN__)
const char* ImGui_ImplWGPU_GetLogLevelName(WGPULogLevel level);
#endif
// (Optional) Helper to create a surface on macOS/Wayland/X11/Window
#ifndef __EMSCRIPTEN__
struct ImGui_ImplWGPU_CreateSurfaceInfo
{
WGPUInstance Instance;
const char* System; // "cocoa" | "wayland" | "x11" | "win32"
void* RawWindow; // NSWindow* | 0 | Window | HWND
void* RawDisplay; // 0 | wl_display* | Display* | 0
void* RawSurface; // | wl_surface* | 0 | 0
void* RawInstance; // 0 | 0 | 0 | HINSTANCE
};
WGPUSurface ImGui_ImplWGPU_CreateWGPUSurfaceHelper(ImGui_ImplWGPU_CreateSurfaceInfo* info);
#endif // #ifndef __EMSCRIPTEN__
#endif // #ifndef IMGUI_DISABLE

View File

@@ -21,6 +21,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-10-19: Inputs: Revert previous change to allow for io.ClearInputKeys() on focus-out not losing gamepad state.
// 2025-09-23: Inputs: Minor optimization not submitting gamepad input if packet number has not changed.
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
// 2025-04-30: Inputs: Fixed an issue where externally losing mouse capture (due to e.g. focus loss) would fail to claim it again the next subsequent click. (#8594)
@@ -125,7 +126,6 @@ struct ImGui_ImplWin32_Data
HMODULE XInputDLL;
PFN_XInputGetCapabilities XInputGetCapabilities;
PFN_XInputGetState XInputGetState;
DWORD XInputPacketNumber;
#endif
ImGui_ImplWin32_Data() { memset((void*)this, 0, sizeof(*this)); }
@@ -357,9 +357,6 @@ static void ImGui_ImplWin32_UpdateGamepads(ImGuiIO& io)
if (!bd->HasGamepad || bd->XInputGetState == nullptr || bd->XInputGetState(0, &xinput_state) != ERROR_SUCCESS)
return;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
if (bd->XInputPacketNumber != 0 && bd->XInputPacketNumber == xinput_state.dwPacketNumber)
return;
bd->XInputPacketNumber = xinput_state.dwPacketNumber;
#define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V)
#define MAP_BUTTON(KEY_NO, BUTTON_ENUM) { io.AddKeyEvent(KEY_NO, (gamepad.wButtons & BUTTON_ENUM) != 0); }

View File

@@ -100,6 +100,7 @@ List of Renderer Backends:
List of high-level Frameworks Backends (combining Platform + Renderer):
imgui_impl_allegro5.cpp
imgui_impl_null.cpp
Emscripten is also supported!
The SDL2+GL, SDL3+GL, GLFW+GL and GLFW+WebGPU examples are all ready to build and run with Emscripten.

View File

@@ -35,6 +35,151 @@ 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.92.5 (Released 2025-11-20)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.5
Breaking Changes:
- Keys: commented out legacy names which were obsoleted in 1.89.0 (August 2022).
- ImGuiKey_ModCtrl --> ImGuiMod_Ctrl
- ImGuiKey_ModShift --> ImGuiMod_Shift
- ImGuiKey_ModAlt --> ImGuiMod_Alt
- ImGuiKey_ModSuper --> ImGuiMod_Super
- IO: commented out legacy io.ClearInputCharacters() obsoleted in 1.89.8 (Aug 2023).
Using io.ClearInputKeys() is enough.
- BeginChild: commented out legacy names which were obsoleted in 1.90.0 (Nov 2023),
1.90.9 (July 2024), 1.91.1 (August 2024). (#462, #7687)
- ImGuiChildFlags_Border --> ImGuiChildFlags_Borders
- ImGuiWindowFlags_NavFlattened --> ImGuiChildFlags_NavFlattened (moved to ImGuiChildFlags).
- ImGuiWindowFlags_AlwaysUseWindowPadding --> ImGuiChildFlags_AlwaysUseWindowPadding (moved to ImGuiChildFlags).
So:
- BeginChild(name, size, 0, ImGuiWindowFlags_NavFlattened) --> BeginChild(name, size, ImGuiChildFlags_NavFlattened, 0)
- BeginChild(name, size, 0, ImGuiWindowFlags_AlwaysUseWindowPadding) --> BeginChild(name, size, ImGuiChildFlags_AlwaysUseWindowPadding, 0)
- Commented out legacy SetItemAllowOverlap() obsoleted in 1.89.7: this never worked right.
Use SetNextItemAllowOverlap() _before_ item instead.
Other Changes:
- Windows:
- Config flag io.ConfigWindowsMoveFromTitleBarOnly is now latched during
Begin(), effectively allowing to change the value on a per-window basis.
(although there is a better internal mechanism for it).
- Fixed single-axis auto-sizing (via double-clicking a border or passing
0.0f on one axis of SetNextWindowSize() call) to take account of remaining
scrollbar on the other axis. (#9060)
- Fixed an issue where repeated calls to SetNextWindowSize() using 0.0f
to auto-size on a given axis would keep marking ini settings as dirty.
- Tables:
- Fixed a bug where nesting BeginTable()->Begin()->BeginTable() would
result in temporarily incorrect state, which would lead to bugs to side effects
in various locations, e.g. GetContentRegionAvail() calls or using clipper. (#9005)
EndTable() was mistakenly restoring a wrong current table.
- Angled headers: fixed an auto-resize feedback loop that could
affect tables with empty non-resizing columns using angled headers, making
them typically flicker back and forth between +0 and +1 pixels.
- Disabled: fixed a bug when a previously enabled item that got nav focus
and then turns disabled could still be activated using keyboard. (#9036)
- InputText:
- When buffer is not resizable, trying to paste contents that cannot
fit will now truncate text to nearest UTF-8 codepoint boundaries,
instead of completely ignoring the paste. (#9029)
- Avoid continuously overwriting ownership of ImGuiKey_Enter/_KeypadEnter
keys in order to allow e.g. external Shortcut override behavior. (#9004)
- When using a callback to reduce/manipulate the value of BufTextLen,
we do not require anymore that CursorPos be clamped by user code. (#9029)
- Fixed an assert when using ImGuiInputTextFlags_ReadOnly and making
underlying contents shorter while text is selected. (#9069, #3237)
(regression from 1.92.3)
- InputTextMultiline: fixed a crash when using ImGuiInputTextFlags_WordWrap and
resizing the parent window while keeping the multi-line field active (which is
most typically achieved when resizing programmatically or via a docking layout
reacting to a platform window resize). (#3237, #9007) [@anton-kl, @ocornut]
- Nav:
- Reworked PageUp/PageDown logic to pick same-page top/bottom page based
on inner rectangle rather than clipping rectangle, ensuring consistent
(but occasionally less practical) navigation result when a window is
partially out of screen. (#787)
- Improved/clarified behavior when requesting PageUp/PageDown from a
focused item which is outside of visible boundaries: now ends up one
page away from focused item. (#9079)
- Clipper: fixed an issue when using up/down from an item outside of
visible bound and using the clipper. (#9079)
- Fonts:
- Calling ImFontAtlas::Clear() mid-frame without re-adding a font will
lead to a more explicit crash.
- Textures:
- Fixed an issue preventing multi-contexts from using each others' fonts
if context 2 runs after context 1's Render() function. (#9039)
- MultiSelect: added ImGuiMultiSelectFlags_NoSelectOnRightClick to disable default
right-click processing, which selects item on mouse down and is designed for
context-menus. (#8200, #9015)
- Groups: fixed an issue reporting IsItemEdited() signal after EndGroup() when
triggered by some widgets e.g. Checkbox(), Selectable() and many others, which
cleared ActiveId at the same time as editing. (#9028)
Note that IsItemDeactivatedAfterEdit() was not affected, only IsItemEdited().
- Misc: standardized casing of keyboard mods in comments and demo, showing
as e.g. "Ctrl" instead of "CTRL".
- CI: Added Dear ImGui Test Suite to CI builds. [@rokups]
- Drag and Drop:
- Added ImGuiDragDropFlags_AcceptDrawAsHovered to make accepting item render
as hovered, which can allow using e.g. Button() as drop target. (#8632)
- Pressing Escape while carrying a payload automatically cancel the
active drag and drop. (#9071)
- Style: added ImGuiCol_DragDropTargetBg, style.DragDropTargetRounding,
style.DragDropTargetBorderSize and style.DragDropTargetPadding to configure
the drop target highlight. (#9056) [@aaronkirkham]
- Demo: About Box: emit infos to convey when IM_ASSERT() macro is disabled,
- so users don't miss out on programming errors being reported.
- so it is included in config/build info submitted in new GitHub Issues.
- Debug Tools:
- Fixed DebugTextEncoding() potentially reading out of bounds when
provided a trailing truncated UTF-8 sequence.
- Metrics: fixed table and columns rect highlight from display when
debug/metrics window is not in the same viewport as the table.
- Backends:
- NULL: added imgui_impl_null platform/renderer backend.
This is designed if you need to run e.g. context with no input or no ouput.
- GLFW: fixed building on Linux platforms where Wayland headers
are not available. (#9024, #8969, #8921, #8920) [@jagot]
- GLFW: lower minimum requirement from GLFW 3.1 to GLFW 3.0. Though
a recent version e.g GLFW 3.4 is highly recommended! (#9055) [@Clownacy]
- GLFW: fixed last `ImGui_ImplGlfw_Shutdown()` not immediately clearing the context
map, which would be detected by leak trackers. (#9075, #8676, #8239, #8069) [@erincatto]
- SDL3: fixed Platform_OpenInShellFn() return value (the return value
was unused in core but might be used by a direct caller). (#9027) [@achabense]
- SDL3: fixed an issue with missing characters events when an already active text
field changes viewports. (#9054)
- Vulkan: added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to
Volk (default to "volk.h"). (#9008, #7722, #6582, #4854) [@mwlasiuk]
- WebGPU: update to compile with Dawn and Emscripten's 4.0.10+
'--use-port=emdawnwebgpu' ports. (#8381, #8898, #7435) [@brutpitt, @trbabb]
When using Emscripten 4.0.10+, backend now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN
instead of IMGUI_IMPL_WEBGPU_BACKEND_WGPU, if neither are specified.
- WebGPU: added various internal/optional helpers to wrap some of the
Dawn/WGPU/Emscripten debacle quirks: (#8381) [@brutpitt]
- ImGui_ImplWGPU_CreateWGPUSurfaceHelper().
- ImGui_ImplWGPU_IsSurfaceStatusError(), ImGui_ImplWGPU_IsSurfaceStatusSubOptimal().
- ImGui_ImplWGPU_DebugPrintAdapterInfo(),
- ImGui_ImplWGPU_GetBackendTypeName(), ImGui_ImplWGPU_GetAdapterTypeName(),
ImGui_ImplWGPU_GetDeviceLostReasonName(), ImGui_ImplWGPU_GetErrorTypeName(),
ImGui_ImplWGPU_GetLogLevelName().
- Win32: Revert 1.92.4 change of comparing dwPacketNumber, which prevents
refreshing accurate gamepad info after focus-out + io.ClearInputKeys(). (#8556)
- Examples:
- NULL: update examples_null to use imgui_impl_null (which is a bit overengineering
but somehow consistent).
- GLFW+WebGPU: update example for latest specs, to work on Emscripten 4.0.10+,
latest Dawn-Native and WGPU-Native. (#8381, #8567, #8191, #7435) [@brutpitt]
- GLFW+WebGPU: removed unnecessary ImGui_ImplWGPU_InvalidateDeviceObjects() call
during surface resize. (#8381)
- SDL2+WebGPU: added new example (Emscripten + native Dawn/WGPU). (#8381) [@brutpitt]
- SDL3+WebGPU: added new example (Emscripten + native Dawn/WGPU). (#8381) [@brutpitt]
- Win32+OpenGL3: enable DPI awareness. (#9083)
-----------------------------------------------------------------------
VERSION 1.92.4 (Released 2025-10-14)
-----------------------------------------------------------------------

View File

@@ -72,7 +72,7 @@ OSX + OpenGL2 example. <BR>
You may prefer to use the GLFW Or SDL backends, which will also support Windows and Linux.)
[example_glfw_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_wgpu/) <BR>
GLFW + WebGPU example. Supports Emscripten (web) or Dawn (desktop) <BR>
GLFW + WebGPU example. Supports Emscripten (web), Dawn (native), WGPU (native). <BR>
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_wgpu.cpp
Note that the 'example_glfw_opengl3' and 'example_sdl2_opengl3' examples also supports Emscripten!
@@ -109,9 +109,11 @@ Note that GLUT/FreeGLUT is largely obsolete software, prefer using GLFW or SDL.
[example_null/](https://github.com/ocornut/imgui/blob/master/examples/example_null/) <BR>
Null example, compile and link imgui, create context, run headless with no inputs and no graphics output. <BR>
= main.cpp <BR>
= main.cpp + imgui_impl_null.cpp<BR>
This is used to quickly test compilation of core imgui files in as many setups as possible.
Because this application doesn't create a window nor a graphic context, there's no graphics output.
Please note that imgui_impl_null itself is a rather empty backend. We provide it for consistency but
it is similarly easy to create a skeleton application without the null backend.
[example_sdl2_directx11/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_directx11/) <BR>
SDL2 + DirectX11 example, Windows only. <BR>
@@ -149,6 +151,11 @@ SDL2 (Win32, Mac, Linux, etc.) + Vulkan example. <BR>
This is quite long and tedious, because: Vulkan. <BR>
For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp.
[example_sdl2_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_wgpu/) <BR>
SDL2 + WebGPU example. Supports Emscripten (web), Dawn (native), WGPU (native). <BR>
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_wgpu.cpp
(note that the 'example_sdl2_opengl3' example also supports Emscripten!)
[example_sdl3_directx11/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_directx11/) <BR>
SDL3 + DirectX11 examples, Windows only. <BR>
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_dx11.cpp <BR>
@@ -177,6 +184,11 @@ SDL3 (Win32, Mac, Linux, etc.) + Vulkan example. <BR>
This is quite long and tedious, because: Vulkan. <BR>
For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp.
[example_sdl3_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_wgpu/) <BR>
SDL3 + WebGPU example. Supports Emscripten (web), Dawn (native), WGPU (native). <BR>
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_wgpu.cpp
(note that the 'example_sdl3_opengl3' example also supports Emscripten!)
[example_win32_directx9/](https://github.com/ocornut/imgui/blob/master/examples/example_win32_directx9/) <BR>
DirectX9 example, Windows only. <BR>
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx9.cpp

View File

@@ -308,7 +308,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- examples: window minimize, maximize (#583)
- examples: provide a zero frame-rate/idle example.
- examples: dx11/dx12: try to use new swapchain blit models (#2970)
- examples: dx11/dx12: try to use new swapchain blit models (#2970, #9031)
- backends: report it better when not able to create texture?
- backends: glfw: could go idle when minimized? if (glfwGetWindowAttrib(window, GLFW_ICONIFIED)) { glfwWaitEvents(); continue; } // issue: DeltaTime will be super high on resume, perhaps provide a way to let impl know (#440)
- backends: opengl: rename imgui_impl_opengl2 to impl_opengl_legacy and imgui_impl_opengl3 to imgui_impl_opengl? (#1900)

View File

@@ -1,9 +1,12 @@
See BACKENDS and EXAMPLES files in the docs/ folder, or on the web at: https://github.com/ocornut/imgui/tree/master/docs
New to Dear ImGui?
- Check out the Getting Started guide: https://github.com/ocornut/imgui/wiki/Getting-Started
- About Backends: docs/BACKENDS.md file, or on the web: https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md
- About Examples: docs/EXAMPLES.md file, or on the web: https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md
Backends = Helper code to facilitate integration with platforms/graphics api (used by Examples + should be used by your app).
Examples = Standalone applications showcasing integration with platforms/graphics api.
Some Examples have extra README files in their respective directory, please check them too!
A few Examples have extra README files in their respective directory, please check them too!
Once Dear ImGui is running (in either examples or your own application/game/engine),
run and refer to ImGui::ShowDemoWindow() in imgui_demo.cpp for the end-user API.

View File

@@ -54,7 +54,6 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
static ImGui_ImplVulkanH_Window g_MainWindowData;
static uint32_t g_MinImageCount = 2;
static bool g_SwapChainRebuild = false;
static VkImageUsageFlags g_SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
static void glfw_error_callback(int error, const char* description)
{
@@ -240,7 +239,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
// Create SwapChain, RenderPass, Framebuffer, etc.
IM_ASSERT(g_MinImageCount >= 2);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, g_SwapChainImageUsage);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, 0);
}
static void CleanupVulkan()
@@ -457,7 +456,7 @@ int main(int, char**)
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
{
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, g_SwapChainImageUsage);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, 0);
g_MainWindowData.FrameIndex = 0;
g_SwapChainRebuild = false;
}

View File

@@ -6,18 +6,30 @@
# * build/Debug/example_glfw_wgpu[.exe]
# * build/example_glfw_wgpu[.exe]
# Building for desktop (WGPU-Native) with WGPU-Native:
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
# 2. unzip the downloaded file in your_preferred_folder
# 3. cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder ("full path" or "relative" starting from current directory)
# 4. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/Debug/example_glfw_wgpu[.exe]
# * build/example_glfw_wgpu[.exe]
# Building for Emscripten:
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
# 2. Install Ninja build system
# 3. emcmake cmake -G Ninja -B build
# (optional) -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py", see ReadMe.md
# 3. cmake --build build
# 4. emrun build/index.html
cmake_minimum_required(VERSION 3.10.2)
cmake_minimum_required(VERSION 3.22) # Dawn requires CMake >= 3.22
project(imgui_example_glfw_wgpu C CXX)
set(IMGUI_EXECUTABLE example_glfw_wgpu)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
endif()
set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17
@@ -25,93 +37,179 @@ set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17
# Dear ImGui
set(IMGUI_DIR ../../)
# Libraries
set(IMGUI_EXAMPLE_SOURCE_FILES
# Example code
main.cpp
# Dear ImGui Backend files
${IMGUI_DIR}/backends/imgui_impl_glfw.cpp
${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp
# Dear ImGui files
${IMGUI_DIR}/imgui.cpp
${IMGUI_DIR}/imgui_draw.cpp
${IMGUI_DIR}/imgui_demo.cpp
${IMGUI_DIR}/imgui_tables.cpp
${IMGUI_DIR}/imgui_widgets.cpp
)
if(EMSCRIPTEN)
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "3.1.57")
set(IMGUI_EMSCRIPTEN_GLFW3 "--use-port=contrib.glfw3" CACHE STRING "Choose between --use-port=contrib.glfw3 and -sUSE_GLFW=3 for GLFW implementation (default to --use-port=contrib.glfw3)")
else()
# cannot use contrib.glfw3 prior to 3.1.57
set(IMGUI_EMSCRIPTEN_GLFW3 "-sUSE_GLFW=3" CACHE STRING "Use -sUSE_GLFW=3 for GLFW implementation" FORCE)
endif()
set(LIBRARIES glfw)
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
if(NOT IMGUI_EMSCRIPTEN_WEBGPU_FLAG) # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG not used, set by current EMSCRIPTEN version
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "4.0.10")
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "--use-port=emdawnwebgpu" CACHE STRING "Choose between --use-port=emdawnwebgpu (Dawn implementation of EMSCRIPTEN) and -sUSE_WEBGPU=1 (WGPU implementation of EMSCRIPTEN, deprecated in 4.0.10): default to --use-port=emdawnwebgpu for EMSCRIPTEN >= 4.0.10")
else()
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "-sUSE_WEBGPU=1" CACHE STRING "Use -sUSE_WEBGPU=1 for EMSCRIPTEN WGPU implementation")
endif()
else() # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG used, check correct version
if(EMSCRIPTEN_VERSION VERSION_LESS "4.0.10" AND "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
# it's necessary EMSCRIPTEN >= v4.0.10 (although "--use-port=path/to/emdawnwebgpu.port.py" is supported/tested from v4.0.8)
message(FATAL_ERROR "emdawnwebgpu needs EMSCRIPTEN version >= 4.0.10")
endif()
endif()
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "3.1.57")
set(IMGUI_EMSCRIPTEN_GLFW3 "--use-port=contrib.glfw3" CACHE STRING "Choose between --use-port=contrib.glfw3 and -sUSE_GLFW=3 for GLFW implementation (default to --use-port=contrib.glfw3)")
else() # cannot use contrib.glfw3 prior to 3.1.57
set(IMGUI_EMSCRIPTEN_GLFW3 "-sUSE_GLFW=3" CACHE STRING "Use -sUSE_GLFW=3 for GLFW implementation" FORCE)
endif()
set(LIBRARIES glfw)
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
else() # Native/Desktop build
# Check DAWN/WGPU directory
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR) # if it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR must be specified
message(FATAL_ERROR "Please specify the Dawn or WGPU base directory")
endif()
if(IMGUI_DAWN_DIR AND IMGUI_WGPU_DIR) # both IMGUI_DAWN_DIR and IMGUI_WGPU_DIR cannot be set
message(FATAL_ERROR "Please specify only one between Dawn / WGPU base directory")
endif()
if(APPLE) # Add SDL2 module to get Surface, with libs and file property for MacOS build
set_source_files_properties(${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++")
set(OS_LIBRARIES "-framework CoreFoundation -framework QuartzCore -framework Metal -framework MetalKit -framework Cocoa")
endif()
find_package(glfw3 REQUIRED)
if(IMGUI_DAWN_DIR) # DAWN-Native build options
list(APPEND CMAKE_PREFIX_PATH ${IMGUI_DAWN_DIR})
find_package(Dawn) # Search for a Dawn installation using IMGUI_DAWN_DIR in CMAKE_PREFIX_PATH
if(Dawn_FOUND)
message("Dawn Installation has been found!")
set(LIBRARIES dawn::webgpu_dawn glfw ${OS_LIBRARIES})
else()
set(IMGUI_DAWN_DIR CACHE PATH "Path to Dawn repository")
option(DAWN_FETCH_DEPENDENCIES "Use fetch_dawn_dependencies.py as an alternative to using depot_tools" ON)
set(DAWN_BUILD_MONOLITHIC_LIBRARY "STATIC" CACHE STRING "Build monolithic library: SHARED, STATIC, or OFF.")
option(DAWN_USE_GLFW OFF) # disable buildin GLFW in DAWN when we use SDL2 / SDL3
# Dawn builds many things by default - disable things we don't need
option(DAWN_BUILD_SAMPLES "Enables building Dawn's samples" OFF)
option(TINT_BUILD_CMD_TOOLS "Build the Tint command line tools" OFF)
option(TINT_BUILD_DOCS "Build documentation" OFF)
option(TINT_BUILD_TESTS "Build tests" OFF)
if(NOT APPLE)
option(TINT_BUILD_MSL_WRITER "Build the MSL output writer" OFF)
endif()
if(WIN32)
option(DAWN_FORCE_SYSTEM_COMPONENT_LOAD "Allow system component fallback" ON)
option(TINT_BUILD_SPV_READER "Build the SPIR-V input reader" OFF)
option(TINT_BUILD_WGSL_READER "Build the WGSL input reader" ON)
option(TINT_BUILD_GLSL_WRITER "Build the GLSL output writer" OFF)
option(TINT_BUILD_GLSL_VALIDATOR "Build the GLSL output validator" OFF)
option(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" ON)
option(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON)
endif()
# check if WAYLAND is the current Session Type and enable DAWN_USE_WAYLAND Wayland option @compile time
# You can override this using: cmake -DDAWN_USE_WAYLAND=X (X = ON | OFF)
if(LINUX)
if($ENV{XDG_SESSION_TYPE} MATCHES wayland)
option(DAWN_USE_WAYLAND "Enable support for Wayland surface" ON)
endif()
endif()
add_subdirectory("${IMGUI_DAWN_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/dawn" EXCLUDE_FROM_ALL)
set(LIBRARIES webgpu_dawn glfw)
endif()
else() # WGPU-Native build options
set(WGPU_NATIVE_LIB_DIR ${IMGUI_WGPU_DIR}/lib)
find_library(WGPU_LIBRARY NAMES libwgpu_native.a wgpu_native.lib wgpu_native HINTS ${WGPU_NATIVE_LIB_DIR} REQUIRED)
if(WIN32)
set(OS_LIBRARIES d3dcompiler ws2_32 userenv bcrypt ntdll opengl32 Propsys RuntimeObject)
elseif(UNIX AND NOT APPLE)
set(OS_LIBRARIES "-lm -ldl")
endif()
set(LIBRARIES glfw ${WGPU_LIBRARY} ${OS_LIBRARIES})
endif()
endif()
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC
${IMGUI_DIR}
${IMGUI_DIR}/backends
)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_EXAMPLE_GLFW_WGPU")
# compiler option only for IMGUI_EXAMPLE_SOURCE_FILES
if (MSVC)
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /W4) # warning level 4
else()
# Dawn wgpu desktop
set(DAWN_FETCH_DEPENDENCIES ON)
set(IMGUI_DAWN_DIR CACHE PATH "Path to Dawn repository")
if (NOT IMGUI_DAWN_DIR)
message(FATAL_ERROR "Please specify the Dawn repository by setting IMGUI_DAWN_DIR")
endif()
option(DAWN_FETCH_DEPENDENCIES "Use fetch_dawn_dependencies.py as an alternative to using depot_tools" ON)
# Dawn builds many things by default - disable things we don't need
option(DAWN_BUILD_SAMPLES "Enables building Dawn's samples" OFF)
option(TINT_BUILD_CMD_TOOLS "Build the Tint command line tools" OFF)
option(TINT_BUILD_DOCS "Build documentation" OFF)
option(TINT_BUILD_TESTS "Build tests" OFF)
if (NOT APPLE)
option(TINT_BUILD_MSL_WRITER "Build the MSL output writer" OFF)
endif()
if(WIN32)
option(TINT_BUILD_SPV_READER "Build the SPIR-V input reader" OFF)
option(TINT_BUILD_WGSL_READER "Build the WGSL input reader" ON)
option(TINT_BUILD_GLSL_WRITER "Build the GLSL output writer" OFF)
option(TINT_BUILD_GLSL_VALIDATOR "Build the GLSL output validator" OFF)
option(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" OFF)
option(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON)
endif()
add_subdirectory("${IMGUI_DAWN_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/dawn" EXCLUDE_FROM_ALL)
set(LIBRARIES webgpu_dawn webgpu_cpp webgpu_glfw glfw)
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC -Wall) # -Wextra -Wpedantic
endif()
add_executable(example_glfw_wgpu
main.cpp
# backend files
${IMGUI_DIR}/backends/imgui_impl_glfw.cpp
${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp
# Dear ImGui files
${IMGUI_DIR}/imgui.cpp
${IMGUI_DIR}/imgui_draw.cpp
${IMGUI_DIR}/imgui_demo.cpp
${IMGUI_DIR}/imgui_tables.cpp
${IMGUI_DIR}/imgui_widgets.cpp
)
IF(NOT EMSCRIPTEN)
target_compile_definitions(example_glfw_wgpu PUBLIC
"IMGUI_IMPL_WEBGPU_BACKEND_DAWN"
)
endif()
target_include_directories(example_glfw_wgpu PUBLIC
${IMGUI_DIR}
${IMGUI_DIR}/backends
)
# In this example IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU internal define is set according to:
# EMSCRIPTEN: by used FLAG
# --use-port=emdawnwebgpu --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN defined
# -sUSE_WEBGPU=1 --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU defined
# NATIVE: by used SDK installation directory
# if IMGUI_DAWN_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN defined
# if IMGUI_WGPU_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU defined
target_link_libraries(example_glfw_wgpu PUBLIC ${LIBRARIES})
if(NOT EMSCRIPTEN) # WegGPU-Native settings
# Set IMGUI_IMPL_WEBGPU_BACKEND_XXXX based on the SDK (directory) used
if(IMGUI_DAWN_DIR)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
if(NOT Dawn_FOUND)
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp)
endif()
else()
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
endif()
target_link_libraries(${IMGUI_EXECUTABLE} PUBLIC ${LIBRARIES})
# Emscripten settings
if(EMSCRIPTEN)
if("${IMGUI_EMSCRIPTEN_GLFW3}" STREQUAL "--use-port=contrib.glfw3")
target_compile_options(example_glfw_wgpu PUBLIC
"${IMGUI_EMSCRIPTEN_GLFW3}"
else() # Emscripten settings
set(CMAKE_EXECUTABLE_SUFFIX ".html")
if("${IMGUI_EMSCRIPTEN_GLFW3}" STREQUAL "--use-port=contrib.glfw3")
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_GLFW3}")
endif()
message(STATUS "Using ${IMGUI_EMSCRIPTEN_GLFW3} GLFW implementation")
if("${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}")
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
else()
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
endif()
message(STATUS "Using ${IMGUI_EMSCRIPTEN_WEBGPU_FLAG} WebGPU implementation")
target_link_options(${IMGUI_EXECUTABLE} PRIVATE
"${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}"
"${IMGUI_EMSCRIPTEN_GLFW3}"
"-sWASM=1"
"-sASYNCIFY=1"
"-sALLOW_MEMORY_GROWTH=1"
"-sNO_EXIT_RUNTIME=0"
"-sASSERTIONS=1"
"-sDISABLE_EXCEPTION_CATCHING=1"
"-sNO_FILESYSTEM=1"
"--shell-file=${CMAKE_CURRENT_LIST_DIR}/../libs/emscripten/shell_minimal.html"
)
endif()
message(STATUS "Using ${IMGUI_EMSCRIPTEN_GLFW3} GLFW implementation")
target_link_options(example_glfw_wgpu PRIVATE
"-sUSE_WEBGPU=1"
"${IMGUI_EMSCRIPTEN_GLFW3}"
"-sWASM=1"
"-sALLOW_MEMORY_GROWTH=1"
"-sNO_EXIT_RUNTIME=0"
"-sASSERTIONS=1"
"-sDISABLE_EXCEPTION_CATCHING=1"
"-sNO_FILESYSTEM=1"
)
set_target_properties(example_glfw_wgpu PROPERTIES OUTPUT_NAME "index")
# copy our custom index.html to build directory
add_custom_command(TARGET example_glfw_wgpu POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_LIST_DIR}/web/index.html" $<TARGET_FILE_DIR:example_glfw_wgpu>
)
set_target_properties(${IMGUI_EXECUTABLE} PROPERTIES OUTPUT_NAME "index")
endif()

View File

@@ -6,8 +6,8 @@
# This Makefile assumes you have loaded emscripten's environment.
# (On Windows, you may need to execute emsdk_env.bat or encmdprompt.bat ahead)
#
# Running `make` will produce three files:
# - web/index.html (current stored in the repository)
# Running `make -f Makefile.emscripten` will produce three files:
# - web/index.html
# - web/index.js
# - web/index.wasm
#
@@ -16,7 +16,7 @@
CC = emcc
CXX = em++
WEB_DIR = web
EXE = $(WEB_DIR)/index.js
EXE = $(WEB_DIR)/index.html
IMGUI_DIR = ../..
SOURCES = main.cpp
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
@@ -34,8 +34,19 @@ EMS =
# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
# Note: For glfw, we use emscripten-glfw port (contrib.glfw3) instead of (-s USE_GLFW=3) to get a better support for High DPI displays.
EMS += -s DISABLE_EXCEPTION_CATCHING=1 --use-port=contrib.glfw3
LDFLAGS += -s USE_WEBGPU=1
LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
LDFLAGS += -s WASM=1
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
LDFLAGS += -s ASYNCIFY=1
LDFLAGS += -s NO_EXIT_RUNTIME=0
LDFLAGS += -s ASSERTIONS=1
# (1) Using legacy WebGPU implementation (Emscripten < 4.0.10)
#EMS += -DIMGUI_IMPL_WEBGPU_BACKEND_WGPU
#LDFLAGS += -s USE_WEBGPU=1
# or (2) Using newer Dawn-based WebGPU port (Emscripten >= 4.0.10)
EMS += --use-port=emdawnwebgpu
LDFLAGS += --use-port=emdawnwebgpu
# Build as single file (binary text encoded in .html file)
#LDFLAGS += -sSINGLE_FILE
@@ -60,7 +71,7 @@ endif
CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
#CPPFLAGS += -g
CPPFLAGS += -Wall -Wformat -Os $(EMS)
#LDFLAGS += --shell-file shell_minimal.html
LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html
LDFLAGS += $(EMS)
##---------------------------------------------------------------------

View File

@@ -1,4 +1,145 @@
## How to Build
## How to Build
---
### Using CMake
#### Building for desktop (WebGPU-native) with Google Dawn:
1. `git clone https://github.com/google/dawn dawn`
2. `cmake -B build -DIMGUI_DAWN_DIR=dawn`
3. `cmake --build build`
The resulting binary will be found at one of the following locations:
* build/Debug/example_glfw_wgpu[.exe]
* build/example_glfw_wgpu[.exe]
#### Building for desktop (WebGPU-Native) with WGPU:
1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
2. unzip the downloaded file in `your_preferred_folder`
3. `cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder` ("full path" or "relative" starting from current directory)
4. `cmake --build build`
The resulting binary will be found at one of the following locations:
* build/Debug/example_glfw_wgpu[.exe]
* build/example_glfw_wgpu[.exe]
#### Building for Emscripten:
1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
2. Install Ninja build system
3. `emcmake cmake -G Ninja -B build`
- (optional) `-DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py"`, see below
4. `cmake --build build`
#### Sync Emscripten with latest Google Dawn:
If you want to sync Emscripten with latest DAWN release it's necessary to download the `port-emdawnwgpu-package` (released daily by Google) here:
https://github.com/google/dawn/releases
Unpack it in your preferred folder and to replace the step 3 with:
3. `emcmake cmake -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py" -G Ninja -B build`
**N.B.**
For the WASM code produced by Emscripten to work correctly, it will also be necessary to have the "corresponding" (or newer) version of Google Canary (nightly build for developers) that includes the latest changes
---
### CMake by step
#### Generate Dawn Native:
- `cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir -B where_to_build_dir`
- Using `IMGUI_DAWN_DIR` set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
#### Generate WGPU Native:
- `cmake -G Ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -B where_to_build_dir`
- Using `IMGUI_WGPU_DIR` set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
#### Generate Emscripten:
- `emcmake cmake -G Ninja -B where_to_build_dir`\
CMake checks the EMSCRIPEN version then:
- if EMS >= 4.0.10 uses `--use-port=emdawnwebgpu` flag to build
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
- if EMS < 4.0.10 uses `-sUSE_WEBGPU=1` flag to build
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
#### Generate Emscripten forcing `-sUSE_WEBGPU=1` deprecated flag even with EMS >= 4.0.10
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="-sUSE_WEBGPU=1" -B where_to_build_dir`
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
#### Generate Emscripten using external WebGPU library (emdawnwebgpu_pkg)
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path_to_emdawnwebgpu_pkg" -B where_to_build_dir`
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
- *To use external WebGPU library it's necessary to have EMS >= 4.0.10 or the minimum requirements specified by the package:*
- https://github.com/google/dawn/releases
#### Build time
Once the procedure for the specific builder is generated, the build command is **always the same**:
- Build using CMake
- `cmake --build where_to_build_dir`
- It will use selected builder to build the example.
- Build explicitly:
- `cd where_to_build_dir`
- `ninja`
- This is the builder chosen during the generation phase
---
### CMake useful options
#### Generator types (alternative to **ninja** bulder):
- `-G Ninja` to build with __ninja__ builder
- `-G "Unix Makefiles"` to build with __make__ builder
- `-G "Visual Studio 17 2022" -A x64` to create a VS 2022 solution (.sln) file, Windows only
- **Native build only**
- Not **officially** supported to build Google Dawn
Example:
- using **make** instead **ninja**:
- `cmake -G "Unix Makefiles" -DIMGUI_DAWN_DIR=path_to_sdk_dir -B where_to_build_dir`
**Syntax is case sensitive and the "" are necessary in case of spaces between words*
#### Directories
- The directory path can be absolute or relative (starting from the current directory)
- It's necessary to use different `where_to_build_dir` for different CMake generations
#### Build type
The default build type is **Debug**
It is possible to use a different build type using:
- `-DCMAKE_BUILD_TYPE=Release`
- `-DCMAKE_BUILD_TYPE=MinSizeRel`
- `-DCMAKE_BUILD_TYPE=RelWithDebInfo`
Example:
- building **Release**:
- `cmake -G ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -DCMAKE_BUILD_TYPE=Release -B where_to_build_dir `
#### GLFW / SDL2 / SDL3 includes, libraries, search paths and package manager
Includes and libraries, by default, are searched in system/compiler paths (environment variables): you can add the path to your development tools to the environment variables without having to modify the `CMakeLists.txt` file.
- e.g. CLang search in path specified from the following environment variables:
- include files: CPATH, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH
- library files: LIBRARY_PATH
If you are using a package manager (**vcpkg** / **conan** / ... ) you need/can to specify it, adding to cmake command:
- `-DCMAKE_TOOLCHAIN_FILE=path/to/package_manager.cmake`
Examples:
- using **vcpkg** package manager it's necessary adding:
- `-DCMAKE_TOOLCHAIN_FILE=<vcpkg_root_dir>/scripts/buildsystems/vcpkg.cmake`
- full cmake command using **vcpkg** package manager:
- `cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir -DCMAKE_TOOLCHAIN_FILE=<vcpkg_root_dir>/scripts/buildsystems/vcpkg.cmake -B where_to_build_dir`
---
### Using makefile
- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
@@ -10,6 +151,8 @@
- Requires recent Emscripten as WGPU is still a work-in-progress API.
---
## How to Run
To run on a local machine:

View File

@@ -12,50 +12,47 @@
#include "imgui_impl_glfw.h"
#include "imgui_impl_wgpu.h"
#include <stdio.h>
#include <stdlib.h>
#include <GLFW/glfw3.h>
// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details.
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <emscripten/html5.h>
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#include <emscripten/html5_webgpu.h>
#include "../libs/emscripten/emscripten_mainloop_stub.h"
#else
#include <webgpu/webgpu_glfw.h>
#endif
#include "../libs/emscripten/emscripten_mainloop_stub.h"
#endif
#include <webgpu/webgpu.h>
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
#include <webgpu/webgpu_cpp.h>
#endif
// Data
static WGPUInstance wgpu_instance = nullptr;
static WGPUDevice wgpu_device = nullptr;
static WGPUSurface wgpu_surface = nullptr;
static WGPUTextureFormat wgpu_preferred_fmt = WGPUTextureFormat_RGBA8Unorm;
static WGPUSwapChain wgpu_swap_chain = nullptr;
static int wgpu_surface_width = 1280;
static int wgpu_surface_height = 800;
static WGPUInstance wgpu_instance = nullptr;
static WGPUDevice wgpu_device = nullptr;
static WGPUSurface wgpu_surface = nullptr;
static WGPUQueue wgpu_queue = nullptr;
static WGPUSurfaceConfiguration wgpu_surface_configuration = {};
static int wgpu_surface_width = 1280;
static int wgpu_surface_height = 800;
// Forward declarations
static bool InitWGPU(GLFWwindow* window);
static void ResizeSurface(int width, int height);
static bool InitWGPU(GLFWwindow* window);
static WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, GLFWwindow* window);
static void glfw_error_callback(int error, const char* description)
{
printf("GLFW Error %d: %s\n", error, description);
}
static void wgpu_error_callback(WGPUErrorType error_type, const char* message, void*)
static void ResizeSurface(int width, int height)
{
const char* error_type_lbl = "";
switch (error_type)
{
case WGPUErrorType_Validation: error_type_lbl = "Validation"; break;
case WGPUErrorType_OutOfMemory: error_type_lbl = "Out of memory"; break;
case WGPUErrorType_Unknown: error_type_lbl = "Unknown"; break;
case WGPUErrorType_DeviceLost: error_type_lbl = "Device lost"; break;
default: error_type_lbl = "Unknown";
}
printf("%s error: %s\n", error_type_lbl, message);
wgpu_surface_configuration.width = wgpu_surface_width = width;
wgpu_surface_configuration.height = wgpu_surface_height = height;
wgpuSurfaceConfigure(wgpu_surface, &wgpu_surface_configuration);
}
// Main code
@@ -84,7 +81,7 @@ int main(int, char**)
glfwTerminate();
return 1;
}
ResizeSurface(wgpu_surface_width, wgpu_surface_height);
glfwShowWindow(window);
// Setup Dear ImGui context
@@ -111,7 +108,7 @@ int main(int, char**)
ImGui_ImplWGPU_InitInfo init_info;
init_info.Device = wgpu_device;
init_info.NumFramesInFlight = 3;
init_info.RenderTargetFormat = wgpu_preferred_fmt;
init_info.RenderTargetFormat = wgpu_surface_configuration.format;
init_info.DepthStencilFormat = WGPUTextureFormat_Undefined;
ImGui_ImplWGPU_Init(&init_info);
@@ -165,10 +162,23 @@ int main(int, char**)
int width, height;
glfwGetFramebufferSize((GLFWwindow*)window, &width, &height);
if (width != wgpu_surface_width || height != wgpu_surface_height)
{
ImGui_ImplWGPU_InvalidateDeviceObjects();
ResizeSurface(width, height);
ImGui_ImplWGPU_CreateDeviceObjects();
// Check surface status for error. If texture is not optimal, try to reconfigure the surface.
WGPUSurfaceTexture surface_texture;
wgpuSurfaceGetCurrentTexture(wgpu_surface, &surface_texture);
if (ImGui_ImplWGPU_IsSurfaceStatusError(surface_texture.status))
{
fprintf(stderr, "Unrecoverable Surface Texture status=%#.8x\n", surface_texture.status);
abort();
}
if (ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(surface_texture.status))
{
if (surface_texture.texture)
wgpuTextureRelease(surface_texture.texture);
if (width > 0 && height > 0)
ResizeSurface(width, height);
continue;
}
// Start the Dear ImGui frame
@@ -216,17 +226,21 @@ int main(int, char**)
// Rendering
ImGui::Render();
#ifndef __EMSCRIPTEN__
// Tick needs to be called in Dawn to display validation errors
wgpuDeviceTick(wgpu_device);
#endif
WGPUTextureViewDescriptor view_desc = {};
view_desc.format = wgpu_surface_configuration.format;
view_desc.dimension = WGPUTextureViewDimension_2D ;
view_desc.mipLevelCount = WGPU_MIP_LEVEL_COUNT_UNDEFINED;
view_desc.arrayLayerCount = WGPU_ARRAY_LAYER_COUNT_UNDEFINED;
view_desc.aspect = WGPUTextureAspect_All;
WGPUTextureView texture_view = wgpuTextureCreateView(surface_texture.texture, &view_desc);
WGPURenderPassColorAttachment color_attachments = {};
color_attachments.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
color_attachments.loadOp = WGPULoadOp_Clear;
color_attachments.storeOp = WGPUStoreOp_Store;
color_attachments.clearValue = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
color_attachments.view = wgpuSwapChainGetCurrentTextureView(wgpu_swap_chain);
color_attachments.view = texture_view;
WGPURenderPassDescriptor render_pass_desc = {};
render_pass_desc.colorAttachmentCount = 1;
@@ -242,14 +256,16 @@ int main(int, char**)
WGPUCommandBufferDescriptor cmd_buffer_desc = {};
WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc);
WGPUQueue wgpu_queue = wgpuDeviceGetQueue(wgpu_device);
wgpuQueueSubmit(wgpu_queue, 1, &cmd_buffer);
#ifndef __EMSCRIPTEN__
wgpuSwapChainPresent(wgpu_swap_chain);
wgpuSurfacePresent(wgpu_surface);
// Tick needs to be called in Dawn to display validation errors
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
wgpuDeviceTick(wgpu_device);
#endif
wgpuTextureViewRelease(color_attachments.view);
#endif
wgpuTextureViewRelease(texture_view);
wgpuRenderPassEncoderRelease(pass);
wgpuCommandEncoderRelease(encoder);
wgpuCommandBufferRelease(cmd_buffer);
@@ -263,93 +279,298 @@ int main(int, char**)
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
wgpuSurfaceUnconfigure(wgpu_surface);
wgpuSurfaceRelease(wgpu_surface);
wgpuQueueRelease(wgpu_queue);
wgpuDeviceRelease(wgpu_device);
wgpuInstanceRelease(wgpu_instance);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
#ifndef __EMSCRIPTEN__
static WGPUAdapter RequestAdapter(WGPUInstance instance)
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
static WGPUAdapter RequestAdapter(wgpu::Instance& instance)
{
auto onAdapterRequestEnded = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, const char* message, void* pUserData)
wgpu::Adapter acquired_adapter;
wgpu::RequestAdapterOptions adapter_options;
auto onRequestAdapter = [&](wgpu::RequestAdapterStatus status, wgpu::Adapter adapter, wgpu::StringView message)
{
if (status == WGPURequestAdapterStatus_Success)
*(WGPUAdapter*)(pUserData) = adapter;
else
printf("Could not get WebGPU adapter: %s\n", message);
};
WGPUAdapter adapter;
wgpuInstanceRequestAdapter(instance, nullptr, onAdapterRequestEnded, (void*)&adapter);
return adapter;
if (status != wgpu::RequestAdapterStatus::Success)
{
printf("Failed to get an adapter: %s\n", message.data);
return;
}
acquired_adapter = std::move(adapter);
};
// Synchronously (wait until) acquire Adapter
wgpu::Future waitAdapterFunc { instance.RequestAdapter(&adapter_options, wgpu::CallbackMode::WaitAnyOnly, onRequestAdapter) };
wgpu::WaitStatus waitStatusAdapter = instance.WaitAny(waitAdapterFunc, UINT64_MAX);
IM_ASSERT(acquired_adapter != nullptr && waitStatusAdapter == wgpu::WaitStatus::Success && "Error on Adapter request");
return acquired_adapter.MoveToCHandle();
}
static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter)
{
// Set device callback functions
wgpu::DeviceDescriptor device_desc;
device_desc.SetDeviceLostCallback(wgpu::CallbackMode::AllowSpontaneous,
[](const wgpu::Device&, wgpu::DeviceLostReason type, wgpu::StringView msg) { fprintf(stderr, "%s error: %s\n", ImGui_ImplWGPU_GetDeviceLostReasonName((WGPUDeviceLostReason)type), msg.data); }
);
device_desc.SetUncapturedErrorCallback(
[](const wgpu::Device&, wgpu::ErrorType type, wgpu::StringView msg) { fprintf(stderr, "%s error: %s\n", ImGui_ImplWGPU_GetErrorTypeName((WGPUErrorType)type), msg.data); }
);
wgpu::Device acquired_device;
auto onRequestDevice = [&](wgpu::RequestDeviceStatus status, wgpu::Device local_device, wgpu::StringView message)
{
if (status != wgpu::RequestDeviceStatus::Success)
{
printf("Failed to get an device: %s\n", message.data);
return;
}
acquired_device = std::move(local_device);
};
// Synchronously (wait until) get Device
wgpu::Future waitDeviceFunc { adapter.RequestDevice(&device_desc, wgpu::CallbackMode::WaitAnyOnly, onRequestDevice) };
wgpu::WaitStatus waitStatusDevice = instance.WaitAny(waitDeviceFunc, UINT64_MAX);
IM_ASSERT(acquired_device != nullptr && waitStatusDevice == wgpu::WaitStatus::Success && "Error on Device request");
return acquired_device.MoveToCHandle();
}
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#ifdef __EMSCRIPTEN__
// Adapter and device initialization via JS
EM_ASYNC_JS( void, getAdapterAndDeviceViaJS, (),
{
if (!navigator.gpu)
throw Error("WebGPU not supported.");
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
Module.preinitializedWebGPUDevice = device;
} );
#else // __EMSCRIPTEN__
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
{
if (status == WGPURequestAdapterStatus_Success)
{
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
*extAdapter = adapter;
}
else
{
printf("Request_adapter status=%#.8x message=%.*s\n", status, (int) message.length, message.data);
}
}
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
{
if (status == WGPURequestDeviceStatus_Success)
{
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
*extDevice = device;
}
else
{
printf("Request_device status=%#.8x message=%.*s\n", status, (int) message.length, message.data);
}
}
static WGPUAdapter RequestAdapter(WGPUInstance& instance)
{
WGPURequestAdapterOptions adapter_options = {};
WGPUAdapter local_adapter;
WGPURequestAdapterCallbackInfo adapterCallbackInfo = {};
adapterCallbackInfo.callback = handle_request_adapter;
adapterCallbackInfo.userdata1 = &local_adapter;
wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
IM_ASSERT(local_adapter && "Error on Adapter request");
return local_adapter;
}
static WGPUDevice RequestDevice(WGPUAdapter& adapter)
{
auto onDeviceRequestEnded = [](WGPURequestDeviceStatus status, WGPUDevice device, const char* message, void* pUserData)
{
if (status == WGPURequestDeviceStatus_Success)
*(WGPUDevice*)(pUserData) = device;
else
printf("Could not get WebGPU device: %s\n", message);
};
WGPUDevice device;
wgpuAdapterRequestDevice(adapter, nullptr, onDeviceRequestEnded, (void*)&device);
return device;
WGPUDevice local_device;
WGPURequestDeviceCallbackInfo deviceCallbackInfo = {};
deviceCallbackInfo.callback = handle_request_device;
deviceCallbackInfo.userdata1 = &local_device;
wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
IM_ASSERT(local_device && "Error on Device request");
return local_device;
}
#endif
#endif // __EMSCRIPTEN__
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
static bool InitWGPU(GLFWwindow* window)
{
wgpu::Instance instance = wgpuCreateInstance(nullptr);
WGPUTextureFormat preferred_fmt = WGPUTextureFormat_Undefined; // acquired from SurfaceCapabilities
#ifdef __EMSCRIPTEN__
wgpu_device = emscripten_webgpu_get_device();
if (!wgpu_device)
return false;
#else
WGPUAdapter adapter = RequestAdapter(instance.Get());
if (!adapter)
return false;
wgpu_device = RequestDevice(adapter);
#endif
// Google DAWN backend: Adapter and Device acquisition, Surface creation
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
wgpu::InstanceDescriptor instance_desc = {};
static constexpr wgpu::InstanceFeatureName timedWaitAny = wgpu::InstanceFeatureName::TimedWaitAny;
instance_desc.requiredFeatureCount = 1;
instance_desc.requiredFeatures = &timedWaitAny;
wgpu::Instance instance = wgpu::CreateInstance(&instance_desc);
wgpu::Adapter adapter = RequestAdapter(instance);
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter.Get());
wgpu_device = RequestDevice(instance, adapter);
// Create the surface.
#ifdef __EMSCRIPTEN__
wgpu::SurfaceDescriptorFromCanvasHTMLSelector canvas_desc = {};
wgpu::EmscriptenSurfaceSourceCanvasHTMLSelector canvas_desc = {};
canvas_desc.selector = "#canvas";
wgpu::SurfaceDescriptor surface_desc = {};
surface_desc.nextInChain = &canvas_desc;
wgpu::Surface surface = instance.CreateSurface(&surface_desc);
wgpu::Adapter adapter = {};
wgpu_preferred_fmt = (WGPUTextureFormat)surface.GetPreferredFormat(adapter);
wgpu_surface = instance.CreateSurface(&surface_desc).MoveToCHandle();
#else
wgpu::Surface surface = wgpu::glfw::CreateSurfaceForWindow(instance, window);
if (!surface)
return false;
wgpu_preferred_fmt = WGPUTextureFormat_BGRA8Unorm;
wgpu_surface = CreateWGPUSurface(instance.Get(), window);
#endif
if (!wgpu_surface)
return false;
// Moving Dawn objects into WGPU handles
wgpu_instance = instance.MoveToCHandle();
wgpu_surface = surface.MoveToCHandle();
wgpuDeviceSetUncapturedErrorCallback(wgpu_device, wgpu_error_callback, nullptr);
WGPUSurfaceCapabilities surface_capabilities = {};
wgpuSurfaceGetCapabilities(wgpu_surface, adapter.Get(), &surface_capabilities);
preferred_fmt = surface_capabilities.formats[0];
// WGPU backend: Adapter and Device acquisition, Surface creation
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
wgpu_instance = wgpuCreateInstance(nullptr);
#ifdef __EMSCRIPTEN__
getAdapterAndDeviceViaJS();
wgpu_device = emscripten_webgpu_get_device();
IM_ASSERT(wgpu_device != nullptr && "Error creating the Device");
WGPUSurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
html_surface_desc.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector;
html_surface_desc.selector = "#canvas";
WGPUSurfaceDescriptor surface_desc = {};
surface_desc.nextInChain = &html_surface_desc.chain;
// Create the surface.
wgpu_surface = wgpuInstanceCreateSurface(wgpu_instance, &surface_desc);
preferred_fmt = wgpuSurfaceGetPreferredFormat(wgpu_surface, {} /* adapter */);
#else // __EMSCRIPTEN__
wgpuSetLogCallback(
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
);
wgpuSetLogLevel(WGPULogLevel_Warn);
WGPUAdapter adapter = RequestAdapter(wgpu_instance);
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter);
wgpu_device = RequestDevice(adapter);
// Create the surface.
wgpu_surface = CreateWGPUSurface(wgpu_instance, window);
if (!wgpu_surface)
return false;
WGPUSurfaceCapabilities surface_capabilities = {};
wgpuSurfaceGetCapabilities(wgpu_surface, adapter, &surface_capabilities);
preferred_fmt = surface_capabilities.formats[0];
#endif // __EMSCRIPTEN__
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
wgpu_surface_configuration.presentMode = WGPUPresentMode_Fifo;
wgpu_surface_configuration.alphaMode = WGPUCompositeAlphaMode_Auto;
wgpu_surface_configuration.usage = WGPUTextureUsage_RenderAttachment;
wgpu_surface_configuration.width = wgpu_surface_width;
wgpu_surface_configuration.height = wgpu_surface_height;
wgpu_surface_configuration.device = wgpu_device;
wgpu_surface_configuration.format = preferred_fmt;
wgpuSurfaceConfigure(wgpu_surface, &wgpu_surface_configuration);
wgpu_queue = wgpuDeviceGetQueue(wgpu_device);
return true;
}
static void ResizeSurface(int width, int height)
// GLFW helper to create a WebGPU surface, used only in WGPU-Native. DAWN-Native already has a built-in function
// As of today (2025/10) there is no "official" support in GLFW to create a surface for WebGPU backend
// This stub uses "low level" GLFW calls to acquire information from a specific Window Manager.
// Currently supported platforms: Windows / Linux (X11 and Wayland) / MacOS. Not necessary nor available with EMSCRIPTEN.
#ifndef __EMSCRIPTEN__
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
#define GLFW_HAS_X11_OR_WAYLAND 1
#else
#define GLFW_HAS_X11_OR_WAYLAND 0
#endif
#ifdef _WIN32
#undef APIENTRY
#ifndef GLFW_EXPOSE_NATIVE_WIN32 // for glfwGetWin32Window()
#define GLFW_EXPOSE_NATIVE_WIN32
#endif
#elif defined(__APPLE__)
#ifndef GLFW_EXPOSE_NATIVE_COCOA // for glfwGetCocoaWindow()
#define GLFW_EXPOSE_NATIVE_COCOA
#endif
#elif GLFW_HAS_X11_OR_WAYLAND
#ifndef GLFW_EXPOSE_NATIVE_X11 // for glfwGetX11Display(), glfwGetX11Window() on Freedesktop (Linux, BSD, etc.)
#define GLFW_EXPOSE_NATIVE_X11
#endif
#ifndef GLFW_EXPOSE_NATIVE_WAYLAND
#if defined(__has_include) && __has_include(<wayland-client.h>)
#define GLFW_EXPOSE_NATIVE_WAYLAND
#endif
#endif
#endif
#include <GLFW/glfw3native.h>
#undef Status // X11 headers are leaking this and also 'Success', 'Always', 'None', all used in DAWN api. Add #undef if necessary.
WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, GLFWwindow* window)
{
if (wgpu_swap_chain)
wgpuSwapChainRelease(wgpu_swap_chain);
wgpu_surface_width = width;
wgpu_surface_height = height;
WGPUSwapChainDescriptor swap_chain_desc = {};
swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment;
swap_chain_desc.format = wgpu_preferred_fmt;
swap_chain_desc.width = width;
swap_chain_desc.height = height;
swap_chain_desc.presentMode = WGPUPresentMode_Fifo;
wgpu_swap_chain = wgpuDeviceCreateSwapChain(wgpu_device, wgpu_surface, &swap_chain_desc);
ImGui_ImplWGPU_CreateSurfaceInfo create_info = {};
create_info.Instance = instance;
#if defined(GLFW_EXPOSE_NATIVE_COCOA)
{
create_info.System = "cocoa";
create_info.RawWindow = (void*)glfwGetCocoaWindow(window);
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND)
{
create_info.System = "wayland";
create_info.RawDisplay = (void*)glfwGetWaylandDisplay();
create_info.RawSurface = (void*)glfwGetWaylandWindow(window);
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
#elif defined(GLFW_EXPOSE_NATIVE_X11)
if (glfwGetPlatform() == GLFW_PLATFORM_X11)
{
create_info.System = "x11";
create_info.RawWindow = (void*)glfwGetX11Window(window);
create_info.RawDisplay = (void*)glfwGetX11Display();
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
#elif defined(GLFW_EXPOSE_NATIVE_WIN32)
{
create_info.System = "win32";
create_info.RawWindow = (void*)glfwGetWin32Window(window);
create_info.RawInstance = (void*)::GetModuleHandle(NULL);
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
#else
#error "Unsupported WebGPU native platform!"
#endif
return nullptr;
}
#endif // #ifndef __EMSCRIPTEN__

View File

@@ -1,84 +0,0 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
<title>Dear ImGui Emscripten+GLFW+WebGPU example</title>
<style>
body { margin: 0; background-color: black }
.emscripten {
position: absolute;
top: 0px;
left: 0px;
margin: 0px;
border: 0;
width: 100%;
height: 100%;
overflow: hidden;
display: block;
image-rendering: optimizeSpeed;
image-rendering: -moz-crisp-edges;
image-rendering: -o-crisp-edges;
image-rendering: -webkit-optimize-contrast;
image-rendering: optimize-contrast;
image-rendering: crisp-edges;
image-rendering: pixelated;
-ms-interpolation-mode: nearest-neighbor;
}
</style>
</head>
<body>
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<script type='text/javascript'>
var Module;
(async () => {
Module = {
preRun: [],
postRun: [],
print: (function() {
return function(text) {
text = Array.prototype.slice.call(arguments).join(' ');
console.log(text);
};
})(),
printErr: function(text) {
text = Array.prototype.slice.call(arguments).join(' ');
console.error(text);
},
canvas: (function() {
var canvas = document.getElementById('canvas');
//canvas.addEventListener("webglcontextlost", function(e) { alert('FIXME: WebGL context lost, please reload the page'); e.preventDefault(); }, false);
return canvas;
})(),
setStatus: function(text) {
console.log("status: " + text);
},
monitorRunDependencies: function(left) {
// no run dependencies to log
}
};
window.onerror = function() {
console.log("onerror: " + event);
};
// Initialize the graphics adapter
{
if (!navigator.gpu) {
throw Error("WebGPU not supported.");
}
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
Module.preinitializedWebGPUDevice = device;
}
{
const js = document.createElement('script');
js.async = true;
js.src = "index.js";
document.body.appendChild(js);
}
})();
</script>
</body>
</html>

View File

@@ -0,0 +1,178 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{1A0BF63C-18EF-4BAE-A8DA-055481B11F5D}</ProjectGuid>
<RootNamespace>example_win32_directx11</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\backends\imgui_impl_null.h" />
<ClInclude Include="..\..\imconfig.h" />
<ClInclude Include="..\..\imgui.h" />
<ClInclude Include="..\..\imgui_internal.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\backends\imgui_impl_null.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\imgui.cpp" />
<ClCompile Include="..\..\imgui_demo.cpp" />
<ClCompile Include="..\..\imgui_draw.cpp" />
<ClCompile Include="..\..\imgui_tables.cpp" />
<ClCompile Include="..\..\imgui_widgets.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\misc\debuggers\imgui.natstepfilter" />
<None Include="..\..\misc\debuggers\imgui.natvis" />
<None Include="..\README.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="imgui">
<UniqueIdentifier>{0587d7a3-f2ce-4d56-b84f-a0005d3bfce6}</UniqueIdentifier>
</Filter>
<Filter Include="sources">
<UniqueIdentifier>{08e36723-ce4f-4cff-9662-c40801cf1acf}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\imconfig.h">
<Filter>imgui</Filter>
</ClInclude>
<ClInclude Include="..\..\imgui.h">
<Filter>imgui</Filter>
</ClInclude>
<ClInclude Include="..\..\imgui_internal.h">
<Filter>imgui</Filter>
</ClInclude>
<ClInclude Include="..\..\backends\imgui_impl_null.h">
<Filter>sources</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\imgui.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_demo.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_draw.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_tables.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\imgui_widgets.cpp">
<Filter>imgui</Filter>
</ClCompile>
<ClCompile Include="..\..\backends\imgui_impl_null.cpp">
<Filter>sources</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\README.txt" />
<None Include="..\..\misc\debuggers\imgui.natvis">
<Filter>imgui</Filter>
</None>
<None Include="..\..\misc\debuggers\imgui.natstepfilter">
<Filter>imgui</Filter>
</None>
</ItemGroup>
</Project>

View File

@@ -4,23 +4,26 @@
#include "imgui.h"
#include <stdio.h>
// For imgui_impl_null: use relative filename + embed implementation directly by including the .cpp file.
// This is to simplify casual building of this example from all sorts of test scripts.
#include "../../backends/imgui_impl_null.h"
#include "../../backends/imgui_impl_null.cpp"
int main(int, char**)
{
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
// Build atlas
//unsigned char* tex_pixels = nullptr;
//int tex_w, tex_h;
//io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_w, &tex_h);
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures;
ImGui_ImplNullPlatform_Init();
ImGui_ImplNullRender_Init();
for (int n = 0; n < 20; n++)
{
printf("NewFrame() %d\n", n);
io.DisplaySize = ImVec2(1920, 1080);
io.DeltaTime = 1.0f / 60.0f;
ImGui_ImplNullPlatform_NewFrame();
ImGui_ImplNullRender_NewFrame();
ImGui::NewFrame();
static float f = 0.0f;
@@ -33,6 +36,8 @@ int main(int, char**)
}
printf("DestroyContext()\n");
ImGui_ImplNullRender_Shutdown();
ImGui_ImplNullPlatform_Shutdown();
ImGui::DestroyContext();
return 0;
}

View File

@@ -210,6 +210,7 @@ int main(int, char**)
bool CreateDeviceD3D(HWND hWnd)
{
// Setup swap chain
// This is a basic setup. Optimally could use e.g. DXGI_SWAP_EFFECT_FLIP_DISCARD and handle fullscreen mode differently. See #8979 for suggestions.
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 2;

View File

@@ -49,7 +49,6 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
static ImGui_ImplVulkanH_Window g_MainWindowData;
static uint32_t g_MinImageCount = 2;
static bool g_SwapChainRebuild = false;
static VkImageUsageFlags g_SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
static void check_vk_result(VkResult err)
{
@@ -231,7 +230,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
// Create SwapChain, RenderPass, Framebuffer, etc.
IM_ASSERT(g_MinImageCount >= 2);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, g_SwapChainImageUsage);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, 0);
}
static void CleanupVulkan()
@@ -477,7 +476,7 @@ int main(int, char**)
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
{
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, g_SwapChainImageUsage);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, 0);
g_MainWindowData.FrameIndex = 0;
g_SwapChainRebuild = false;
}

View File

@@ -0,0 +1,205 @@
# Building for desktop (WebGPU-native) with Dawn:
# 1. git clone https://github.com/google/dawn dawn
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
# 3. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/Debug/example_sdl2_wgpu[.exe]
# * build/example_sdl2_wgpu[.exe]
# Building for desktop (WGPU-Native) with WGPU-Native:
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
# 2. unzip the downloaded file in your_preferred_folder
# 3. cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder ("full path" or "relative" starting from current directory)
# 4. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/Debug/example_sdl2_wgpu[.exe]
# * build/example_sdl2_wgpu[.exe]
# Building for Emscripten:
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
# 2. Install Ninja build system
# 3. emcmake cmake -G Ninja -B build
# (optional) -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py", see ReadMe.md
# 3. cmake --build build
# 4. emrun build/index.html
cmake_minimum_required(VERSION 3.22) # Dawn requires CMake >= 3.22
project(imgui_example_sdl2_wgpu C CXX)
set(IMGUI_EXECUTABLE example_sdl2_wgpu)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
endif()
set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17
# Dear ImGui
set(IMGUI_DIR ../../)
# ImGui example commons source files
set(IMGUI_EXAMPLE_SOURCE_FILES
main.cpp
# backend files
${IMGUI_DIR}/backends/imgui_impl_sdl2.cpp
${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp
# Dear ImGui files
${IMGUI_DIR}/imgui.cpp
${IMGUI_DIR}/imgui_draw.cpp
${IMGUI_DIR}/imgui_demo.cpp
${IMGUI_DIR}/imgui_tables.cpp
${IMGUI_DIR}/imgui_widgets.cpp
)
if(EMSCRIPTEN)
if(NOT IMGUI_EMSCRIPTEN_WEBGPU_FLAG) # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG not used, set by current EMSCRIPTEN version
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "4.0.10")
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "--use-port=emdawnwebgpu" CACHE STRING "Choose between --use-port=emdawnwebgpu (Dawn implementation of EMSCRIPTEN) and -sUSE_WEBGPU=1 (WGPU implementation of EMSCRIPTEN, deprecated in 4.0.10): default to --use-port=emdawnwebgpu for EMSCRIPTEN >= 4.0.10")
else()
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "-sUSE_WEBGPU=1" CACHE STRING "Use -sUSE_WEBGPU=1 for EMSCRIPTEN WGPU implementation")
endif()
else() # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG used, check correct version
if(EMSCRIPTEN_VERSION VERSION_LESS "4.0.10" AND "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
# it's necessary EMSCRIPTEN >= v4.0.10 (although "--use-port=path/to/emdawnwebgpu.port.py" is supported/tested from v4.0.8)
message(FATAL_ERROR "emdawnwebgpu needs EMSCRIPTEN version >= 4.0.10")
endif()
endif()
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
else() # Native/Desktop build
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR) # if it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR must be specified
message(FATAL_ERROR "Please specify the Dawn or WGPU base directory")
endif()
if(IMGUI_DAWN_DIR AND IMGUI_WGPU_DIR) # both IMGUI_DAWN_DIR and IMGUI_WGPU_DIR cannot be set
message(FATAL_ERROR "Please specify only one between Dawn / WGPU base directory")
endif()
if(APPLE) # Add SDL2 module to get Surface, with libs and file property for MacOS build
set_source_files_properties(${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++")
set(OS_LIBRARIES "-framework CoreFoundation -framework QuartzCore -framework Metal -framework MetalKit -framework Cocoa")
endif()
find_package(SDL2 REQUIRED) # SDL_MAIN_HANDLED
if(IMGUI_DAWN_DIR) # DAWN-Native build options
list(APPEND CMAKE_PREFIX_PATH ${IMGUI_DAWN_DIR})
find_package(Threads) # required from Dawn installation
find_package(Dawn) # Search for a Dawn installation using IMGUI_DAWN_DIR in CMAKE_PREFIX_PATH
if(Dawn_FOUND)
message("Dawn Installation has been found!")
set(LIBRARIES dawn::webgpu_dawn ${OS_LIBRARIES})
else()
set(IMGUI_DAWN_DIR CACHE PATH "Path to Dawn repository")
option(DAWN_USE_GLFW OFF) # disable buildin GLFW in DAWN when we use SDL2 / SDL3
option(DAWN_FETCH_DEPENDENCIES "Use fetch_dawn_dependencies.py as an alternative to using depot_tools" ON)
set(DAWN_BUILD_MONOLITHIC_LIBRARY "STATIC" CACHE STRING "Build monolithic library: SHARED, STATIC, or OFF.")
# Dawn builds many things by default - disable things we don't need
option(DAWN_BUILD_SAMPLES "Enables building Dawn's samples" OFF)
option(TINT_BUILD_CMD_TOOLS "Build the Tint command line tools" OFF)
option(TINT_BUILD_DOCS "Build documentation" OFF)
option(TINT_BUILD_TESTS "Build tests" OFF)
if(NOT APPLE)
option(TINT_BUILD_MSL_WRITER "Build the MSL output writer" OFF)
endif()
if(WIN32)
option(DAWN_FORCE_SYSTEM_COMPONENT_LOAD "Allow system component fallback" ON)
option(TINT_BUILD_SPV_READER "Build the SPIR-V input reader" OFF)
option(TINT_BUILD_WGSL_READER "Build the WGSL input reader" ON)
option(TINT_BUILD_GLSL_WRITER "Build the GLSL output writer" OFF)
option(TINT_BUILD_GLSL_VALIDATOR "Build the GLSL output validator" OFF)
option(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" ON)
option(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON)
endif()
# check if WAYLAND is the current Session Type and enable DAWN_USE_WAYLAND Wayland option @compile time
# You can override this using: cmake -DDAWN_USE_WAYLAND=X (X = ON | OFF)
if(LINUX)
if($ENV{XDG_SESSION_TYPE} MATCHES wayland)
option(DAWN_USE_WAYLAND "Enable support for Wayland surface" ON)
endif()
endif()
add_subdirectory("${IMGUI_DAWN_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/dawn" EXCLUDE_FROM_ALL)
set(LIBRARIES webgpu_dawn ${OS_LIBRARIES})
endif()
else() # WGPU-Native build options
set(WGPU_NATIVE_LIB_DIR ${IMGUI_WGPU_DIR}/lib)
find_library(WGPU_LIBRARY NAMES libwgpu_native.a wgpu_native.lib wgpu_native HINTS ${WGPU_NATIVE_LIB_DIR} REQUIRED)
if(WIN32)
set(OS_LIBRARIES d3dcompiler ws2_32 userenv bcrypt ntdll opengl32 Propsys RuntimeObject)
elseif(UNIX AND NOT APPLE)
set(OS_LIBRARIES "-lm -ldl")
endif()
set(LIBRARIES ${WGPU_LIBRARY} ${OS_LIBRARIES})
endif()
endif()
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC
${IMGUI_DIR}
${IMGUI_DIR}/backends
${SDL2_INCLUDE_DIRS}
)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_EXAMPLE_SDL2_WGPU")
# compiler option only for IMGUI_EXAMPLE_SOURCE_FILES
if (MSVC)
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /W4) # warning level 4
else()
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC -Wall) # -Wextra -Wpedantic
endif()
# IMGUI_IMPL_WEBGPU_BACKEND_DAWN/WGPU internal define is set according to:
# EMSCRIPTEN: by used FLAG
# --use-port=emdawnwebgpu --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled (+EMSCRIPTEN)
# -sUSE_WEBGPU=1 --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU enabled (+EMSCRIPTEN)
# NATIVE: by used SDK installation directory
# if IMGUI_DAWN_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled
# if IMGUI_WGPU_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU enabled
if(NOT EMSCRIPTEN) # WegGPU-Native settings
if(IMGUI_DAWN_DIR)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
if(NOT Dawn_FOUND)
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp)
endif()
else()
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
endif()
target_link_libraries(${IMGUI_EXECUTABLE} PUBLIC ${LIBRARIES} ${SDL2_LIBRARIES})
else() # Emscripten settings
set(CMAKE_EXECUTABLE_SUFFIX ".html")
if("${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}")
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
else()
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
endif()
message(STATUS "Using ${IMGUI_EMSCRIPTEN_WEBGPU_FLAG} WebGPU implementation")
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "-sUSE_SDL=2")
target_link_options(${IMGUI_EXECUTABLE} PRIVATE
"${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}"
"-sUSE_SDL=2"
"-sWASM=1"
"-sASYNCIFY=1"
"-sALLOW_MEMORY_GROWTH=1"
"-sNO_EXIT_RUNTIME=0"
"-sASSERTIONS=1"
"-sDISABLE_EXCEPTION_CATCHING=1"
"-sNO_FILESYSTEM=1"
"--shell-file=${CMAKE_CURRENT_LIST_DIR}/../libs/emscripten/shell_minimal.html"
)
set_target_properties(${IMGUI_EXECUTABLE} PROPERTIES OUTPUT_NAME "index")
endif()

View File

@@ -0,0 +1,103 @@
#
# Makefile to use with emscripten
# See https://emscripten.org/docs/getting_started/downloads.html
# for installation instructions.
#
# This Makefile assumes you have loaded emscripten's environment.
# (On Windows, you may need to execute emsdk_env.bat or encmdprompt.bat ahead)
#
# Running `make -f Makefile.emscripten` will produce three files:
# - web/index.html
# - web/index.js
# - web/index.wasm
#
# All three are needed to run the demo.
CC = emcc
CXX = em++
WEB_DIR = web
EXE = $(WEB_DIR)/index.html
IMGUI_DIR = ../..
SOURCES = main.cpp
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl2.cpp $(IMGUI_DIR)/backends/imgui_impl_wgpu.cpp
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
CPPFLAGS =
LDFLAGS =
EMS =
##---------------------------------------------------------------------
## EMSCRIPTEN OPTIONS
##---------------------------------------------------------------------
# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
EMS += -s USE_SDL=2
EMS += -s DISABLE_EXCEPTION_CATCHING=1
LDFLAGS += -s WASM=1
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
LDFLAGS += -s ASYNCIFY=1
LDFLAGS += -s NO_EXIT_RUNTIME=0
LDFLAGS += -s ASSERTIONS=1
# (1) Using legacy WebGPU implementation (Emscripten < 4.0.10)
#EMS += -DIMGUI_IMPL_WEBGPU_BACKEND_WGPU
#LDFLAGS += -s USE_WEBGPU=1
# or (2) Using newer Dawn-based WebGPU port (Emscripten >= 4.0.10)
EMS += --use-port=emdawnwebgpu
LDFLAGS += --use-port=emdawnwebgpu
# Build as single file (binary text encoded in .html file)
#LDFLAGS += -sSINGLE_FILE
# Emscripten allows preloading a file or folder to be accessible at runtime.
# The Makefile for this example project suggests embedding the misc/fonts/ folder into our application, it will then be accessible as "/fonts"
# See documentation for more details: https://emscripten.org/docs/porting/files/packaging_files.html
# (Default value is 0. Set to 1 to enable file-system and include the misc/fonts/ folder as part of the build.)
USE_FILE_SYSTEM ?= 0
ifeq ($(USE_FILE_SYSTEM), 0)
LDFLAGS += -s NO_FILESYSTEM=1
CPPFLAGS += -DIMGUI_DISABLE_FILE_FUNCTIONS
endif
ifeq ($(USE_FILE_SYSTEM), 1)
LDFLAGS += --no-heap-copy --preload-file ../../misc/fonts@/fonts
endif
##---------------------------------------------------------------------
## FINAL BUILD FLAGS
##---------------------------------------------------------------------
CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
#CPPFLAGS += -g
CPPFLAGS += -Wall -Wformat -Os $(EMS)
LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html
LDFLAGS += $(EMS)
##---------------------------------------------------------------------
## BUILD RULES
##---------------------------------------------------------------------
%.o:%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/backends/%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
all: $(EXE)
@echo Build complete for $(EXE)
$(WEB_DIR):
mkdir $@
serve: all
python3 -m http.server -d $(WEB_DIR)
$(EXE): $(OBJS) $(WEB_DIR)
$(CXX) -o $@ $(OBJS) $(LDFLAGS)
clean:
rm -f $(EXE) $(OBJS) $(WEB_DIR)/*.js $(WEB_DIR)/*.wasm $(WEB_DIR)/*.wasm.pre

View File

@@ -0,0 +1,167 @@
## How to Build
---
### Using CMake
#### Building for desktop (WebGPU-native) with Google Dawn:
1. `git clone https://github.com/google/dawn dawn`
2. `cmake -B build -DIMGUI_DAWN_DIR=dawn`
3. `cmake --build build`
The resulting binary will be found at one of the following locations:
* build/Debug/example_sdl2_wgpu[.exe]
* build/example_sdl2_wgpu[.exe]
#### Building for desktop (WebGPU-Native) with WGPU:
1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
2. unzip the downloaded file in `your_preferred_folder`
3. `cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder` ("full path" or "relative" starting from current directory)
4. `cmake --build build`
The resulting binary will be found at one of the following locations:
* build/Debug/example_sdl2_wgpu[.exe]
* build/example_sdl2_wgpu[.exe]
#### Building for Emscripten:
1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
2. Install Ninja build system
3. `emcmake cmake -G Ninja -B build`
- (optional) `-DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py"`, see below
4. `cmake --build build`
#### Sync Emscripten with latest Google Dawn:
If you want to sync Emscripten with latest DAWN release it's necessary to download the `port-emdawnwgpu-package` (released daily by Google) here:
https://github.com/google/dawn/releases
Unpack it in your preferred folder and to replace the step 3 with:
3. `emcmake cmake -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py" -G Ninja -B build`
**N.B.**
For the WASM code produced by Emscripten to work correctly, it will also be necessary to have the "corresponding" (or newer) version of Google Canary (nightly build for developers) that includes the latest changes
---
### CMake by step
#### Generate Dawn Native:
- `cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir -B where_to_build_dir`
- Using `IMGUI_DAWN_DIR` set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
#### Generate WGPU Native:
- `cmake -G Ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -B where_to_build_dir`
- Using `IMGUI_WGPU_DIR` set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
#### Generate Emscripten:
- `emcmake cmake -G Ninja -B where_to_build_dir`\
CMake checks the EMSCRIPEN version then:
- if EMS >= 4.0.10 uses `--use-port=emdawnwebgpu` flag to build
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
- if EMS < 4.0.10 uses `-sUSE_WEBGPU=1` flag to build
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
#### Generate Emscripten forcing `-sUSE_WEBGPU=1` deprecated flag even with EMS >= 4.0.10
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="-sUSE_WEBGPU=1" -B where_to_build_dir`
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
#### Generate Emscripten using external WebGPU library (emdawnwebgpu_pkg)
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path_to_emdawnwebgpu_pkg" -B where_to_build_dir`
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
- *To use external WebGPU library it's necessary to have EMS >= 4.0.10 or the minimum requirements specified by the package:*
- https://github.com/google/dawn/releases
#### Build time
Once the procedure for the specific builder is generated, the build command is **always the same**:
- Build using CMake
- `cmake --build where_to_build_dir`
- It will use selected builder to build the example.
- Build explicitly:
- `cd where_to_build_dir`
- `ninja`
- This is the builder chosen during the generation phase
---
### CMake useful options
#### Generator types (alternative to **ninja** bulder):
- `-G Ninja` to build with __ninja__ builder
- `-G "Unix Makefiles"` to build with __make__ builder
- `-G "Visual Studio 17 2022" -A x64` to create a VS 2022 solution (.sln) file, Windows only
- **Native build only**
- Not **officially** supported to build Google Dawn
Example:
- using **make** instead **ninja**:
- `cmake -G "Unix Makefiles" -DIMGUI_DAWN_DIR=path_to_sdk_dir -B where_to_build_dir`
**Syntax is case sensitive and the "" are necessary in case of spaces between words*
#### Directories
- The directory path can be absolute or relative (starting from the current directory)
- It's necessary to use different `where_to_build_dir` for different CMake generations
#### Build type
The default build type is **Debug**
It is possible to use a different build type using:
- `-DCMAKE_BUILD_TYPE=Release`
- `-DCMAKE_BUILD_TYPE=MinSizeRel`
- `-DCMAKE_BUILD_TYPE=RelWithDebInfo`
Example:
- building **Release**:
- `cmake -G ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -DCMAKE_BUILD_TYPE=Release -B where_to_build_dir `
#### GLFW / SDL2 / SDL3 includes, libraries, search paths and package manager
Includes and libraries, by default, are searched in system/compiler paths (environment variables): you can add the path to your development tools to the environment variables without having to modify the `CMakeLists.txt` file.
- e.g. CLang search in path specified from the following environment variables:
- include files: CPATH, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH
- library files: LIBRARY_PATH
If you are using a package manager (**vcpkg** / **conan** / ... ) you need/can to specify it, adding to cmake command:
- `-DCMAKE_TOOLCHAIN_FILE=path/to/package_manager.cmake`
Examples:
- using **vcpkg** package manager it's necessary adding:
- `-DCMAKE_TOOLCHAIN_FILE=<vcpkg_root_dir>/scripts/buildsystems/vcpkg.cmake`
- full cmake command using **vcpkg** package manager:
- `cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir -DCMAKE_TOOLCHAIN_FILE=<vcpkg_root_dir>/scripts/buildsystems/vcpkg.cmake -B where_to_build_dir`
---
### Using makefile
- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
- Depending on your configuration, in Windows you may need to run `emsdk/emsdk_env.bat` in your console to access the Emscripten command-line tools.
- You may also refer to our [Continuous Integration setup](https://github.com/ocornut/imgui/tree/master/.github/workflows) for Emscripten setup.
- Then build using `make -f Makefile.emscripten` while in the `example_glfw_wgpu/` directory.
- Requires recent Emscripten as WGPU is still a work-in-progress API.
---
## How to Run
To run on a local machine:
- Make sure your browse supports WGPU and it is enabled. WGPU is still WIP not enabled by default in most browser.
- `make serve` will use Python3 to spawn a local webserver, you can then browse http://localhost:8000 to access your build.
- Otherwise, generally you will need a local webserver:
- Quoting [https://emscripten.org/docs/getting_started](https://emscripten.org/docs/getting_started/Tutorial.html#generating-html):<br>
_"Unfortunately several browsers (including Chrome, Safari, and Internet Explorer) do not support file:// [XHR](https://emscripten.org/docs/site/glossary.html#term-xhr) requests, and cant load extra files needed by the HTML (like a .wasm file, or packaged file data as mentioned lower down). For these browsers youll need to serve the files using a [local webserver](https://emscripten.org/docs/getting_started/FAQ.html#faq-local-webserver) and then open http://localhost:8000/hello.html."_
- Emscripten SDK has a handy `emrun` command: `emrun web/example_glfw_wgpu.html --browser firefox` which will spawn a temporary local webserver (in Firefox). See https://emscripten.org/docs/compiling/Running-html-files-with-emrun.html for details.
- You may use Python 3 builtin webserver: `python -m http.server -d web` (this is what `make serve` uses).
- You may use Python 2 builtin webserver: `cd web && python -m SimpleHTTPServer`.
- If you are accessing the files over a network, certain browsers, such as Firefox, will restrict Gamepad API access to secure contexts only (e.g. https only).

View File

@@ -0,0 +1,541 @@
// Dear ImGui: standalone example application for using SDL2 + WebGPU
// - Emscripten is supported for publishing on web. See https://emscripten.org.
// - Dawn is used as a WebGPU implementation on desktop.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
#include "imgui.h"
#include "imgui_impl_sdl2.h"
#include "imgui_impl_wgpu.h"
#include <stdio.h>
#include <SDL.h>
// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details.
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <emscripten/html5.h>
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#include <emscripten/html5_webgpu.h>
#endif
#include "../libs/emscripten/emscripten_mainloop_stub.h"
#endif
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
#include <webgpu/webgpu_cpp.h>
#endif
// Data
static WGPUInstance wgpu_instance = nullptr;
static WGPUDevice wgpu_device = nullptr;
static WGPUSurface wgpu_surface = nullptr;
static WGPUQueue wgpu_queue = nullptr;
static WGPUSurfaceConfiguration wgpu_surface_configuration = {};
static int wgpu_surface_width = 1280;
static int wgpu_surface_height = 800;
// Forward declarations
static bool InitWGPU(SDL_Window* window);
WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, SDL_Window* window);
static void ResizeSurface(int width, int height)
{
wgpu_surface_configuration.width = wgpu_surface_width = width;
wgpu_surface_configuration.height = wgpu_surface_height = height;
wgpuSurfaceConfigure(wgpu_surface, (WGPUSurfaceConfiguration*)&wgpu_surface_configuration);
}
// Main code
int main(int, char**)
{
// Setup SDL
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER);
// Create window with graphics context
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE;
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+WebGPU example", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, wgpu_surface_width, wgpu_surface_height, window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return 1;
}
// Initialize WGPU
InitWGPU(window);
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
// Setup Platform/Renderer backends
ImGui_ImplSDL2_InitForOther(window);
ImGui_ImplWGPU_InitInfo init_info;
init_info.Device = wgpu_device;
init_info.NumFramesInFlight = 3;
init_info.RenderTargetFormat = wgpu_surface_configuration.format;
init_info.DepthStencilFormat = WGPUTextureFormat_Undefined;
ImGui_ImplWGPU_Init(&init_info);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - Read 'docs/FONTS.md' for more instructions and details. If you like the default font but want it to scale better, consider using the 'ProggyVector' from the same author!
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
// - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details.
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
#ifndef IMGUI_DISABLE_FILE_FUNCTIONS
//io.Fonts->AddFontFromFileTTF("fonts/segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf");
//io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf");
//ImFont* font = io.Fonts->AddFontFromFileTTF("fonts/ArialUni.ttf");
//IM_ASSERT(font != nullptr);
#endif
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop
bool done = false;
#ifdef __EMSCRIPTEN__
// For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file.
// You may manually call LoadIniSettingsFromMemory() to load settings from your own storage.
io.IniFilename = nullptr;
EMSCRIPTEN_MAINLOOP_BEGIN
#else
while (!done)
#endif
{
// Poll and handle events (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
SDL_Event event;
while (SDL_PollEvent(&event))
{
ImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_QUIT)
done = true;
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
done = true;
}
// React to changes in screen size
int width, height;
SDL_GetWindowSize(window, &width, &height);
if (width != wgpu_surface_width || height != wgpu_surface_height)
ResizeSurface(width, height);
// Check surface status for error. If texture is not optimal, try to reconfigure the surface.
WGPUSurfaceTexture surface_texture;
wgpuSurfaceGetCurrentTexture(wgpu_surface, &surface_texture);
if (ImGui_ImplWGPU_IsSurfaceStatusError(surface_texture.status))
{
fprintf(stderr, "Unrecoverable Surface Texture status=%#.8x\n", surface_texture.status);
abort();
}
if (ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(surface_texture.status))
{
if (surface_texture.texture)
wgpuTextureRelease(surface_texture.texture);
if (width > 0 && height > 0)
ResizeSurface(width, height);
continue;
}
// Start the Dear ImGui frame
ImGui_ImplWGPU_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
ImGui::End();
}
// 3. Show another simple window.
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
// Rendering
ImGui::Render();
WGPUTextureViewDescriptor view_desc = {};
view_desc.format = wgpu_surface_configuration.format;
view_desc.dimension = WGPUTextureViewDimension_2D;
view_desc.mipLevelCount = WGPU_MIP_LEVEL_COUNT_UNDEFINED;
view_desc.arrayLayerCount = WGPU_ARRAY_LAYER_COUNT_UNDEFINED;
view_desc.aspect = WGPUTextureAspect_All;
WGPUTextureView texture_view = wgpuTextureCreateView(surface_texture.texture, &view_desc);
WGPURenderPassColorAttachment color_attachments = {};
color_attachments.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
color_attachments.loadOp = WGPULoadOp_Clear;
color_attachments.storeOp = WGPUStoreOp_Store;
color_attachments.clearValue = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
color_attachments.view = texture_view;
WGPURenderPassDescriptor render_pass_desc = {};
render_pass_desc.colorAttachmentCount = 1;
render_pass_desc.colorAttachments = &color_attachments;
render_pass_desc.depthStencilAttachment = nullptr;
WGPUCommandEncoderDescriptor enc_desc = {};
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(wgpu_device, &enc_desc);
WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(encoder, &render_pass_desc);
ImGui_ImplWGPU_RenderDrawData(ImGui::GetDrawData(), pass);
wgpuRenderPassEncoderEnd(pass);
WGPUCommandBufferDescriptor cmd_buffer_desc = {};
WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc);
wgpuQueueSubmit(wgpu_queue, 1, &cmd_buffer);
#ifndef __EMSCRIPTEN__
wgpuSurfacePresent(wgpu_surface);
// Tick needs to be called in Dawn to display validation errors
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
wgpuDeviceTick(wgpu_device);
#endif
#endif
wgpuTextureViewRelease(texture_view);
wgpuRenderPassEncoderRelease(pass);
wgpuCommandEncoderRelease(encoder);
wgpuCommandBufferRelease(cmd_buffer);
}
#ifdef __EMSCRIPTEN__
EMSCRIPTEN_MAINLOOP_END;
#endif
// Cleanup
ImGui_ImplWGPU_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
wgpuSurfaceUnconfigure(wgpu_surface);
wgpuSurfaceRelease(wgpu_surface);
wgpuQueueRelease(wgpu_queue);
wgpuDeviceRelease(wgpu_device);
wgpuInstanceRelease(wgpu_instance);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
static WGPUAdapter RequestAdapter(wgpu::Instance& instance)
{
wgpu::Adapter acquired_adapter;
wgpu::RequestAdapterOptions adapter_options;
auto onRequestAdapter = [&](wgpu::RequestAdapterStatus status, wgpu::Adapter adapter, wgpu::StringView message)
{
if (status != wgpu::RequestAdapterStatus::Success)
{
printf("Failed to get an adapter: %s\n", message.data);
return;
}
acquired_adapter = std::move(adapter);
};
// Synchronously (wait until) acquire Adapter
wgpu::Future waitAdapterFunc { instance.RequestAdapter(&adapter_options, wgpu::CallbackMode::WaitAnyOnly, onRequestAdapter) };
wgpu::WaitStatus waitStatusAdapter = instance.WaitAny(waitAdapterFunc, UINT64_MAX);
IM_ASSERT(acquired_adapter != nullptr && waitStatusAdapter == wgpu::WaitStatus::Success && "Error on Adapter request");
return acquired_adapter.MoveToCHandle();
}
static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter)
{
// Set device callback functions
wgpu::DeviceDescriptor device_desc;
device_desc.SetDeviceLostCallback(wgpu::CallbackMode::AllowSpontaneous,
[](const wgpu::Device&, wgpu::DeviceLostReason type, wgpu::StringView msg) { fprintf(stderr, "%s error: %s\n", ImGui_ImplWGPU_GetDeviceLostReasonName((WGPUDeviceLostReason)type), msg.data); }
);
device_desc.SetUncapturedErrorCallback(
[](const wgpu::Device&, wgpu::ErrorType type, wgpu::StringView msg) { fprintf(stderr, "%s error: %s\n", ImGui_ImplWGPU_GetErrorTypeName((WGPUErrorType)type), msg.data); }
);
wgpu::Device acquired_device;
auto onRequestDevice = [&](wgpu::RequestDeviceStatus status, wgpu::Device local_device, wgpu::StringView message)
{
if (status != wgpu::RequestDeviceStatus::Success)
{
printf("Failed to get an device: %s\n", message.data);
return;
}
acquired_device = std::move(local_device);
};
// Synchronously (wait until) get Device
wgpu::Future waitDeviceFunc { adapter.RequestDevice(&device_desc, wgpu::CallbackMode::WaitAnyOnly, onRequestDevice) };
wgpu::WaitStatus waitStatusDevice = instance.WaitAny(waitDeviceFunc, UINT64_MAX);
IM_ASSERT(acquired_device != nullptr && waitStatusDevice == wgpu::WaitStatus::Success && "Error on Device request");
return acquired_device.MoveToCHandle();
}
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#ifdef __EMSCRIPTEN__
// Adapter and device initialization via JS
EM_ASYNC_JS( void, getAdapterAndDeviceViaJS, (),
{
if (!navigator.gpu)
throw Error("WebGPU not supported.");
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
Module.preinitializedWebGPUDevice = device;
} );
#else // __EMSCRIPTEN__
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
{
if (status == WGPURequestAdapterStatus_Success)
{
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
*extAdapter = adapter;
}
else
{
printf("Request_adapter status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
}
}
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
{
if (status == WGPURequestDeviceStatus_Success)
{
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
*extDevice = device;
}
else
{
printf("Request_device status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
}
}
static WGPUAdapter RequestAdapter(WGPUInstance& instance)
{
WGPURequestAdapterOptions adapter_options = {};
WGPUAdapter local_adapter;
WGPURequestAdapterCallbackInfo adapterCallbackInfo = {};
adapterCallbackInfo.callback = handle_request_adapter;
adapterCallbackInfo.userdata1 = &local_adapter;
wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
IM_ASSERT(local_adapter && "Error on Adapter request");
return local_adapter;
}
static WGPUDevice RequestDevice(WGPUAdapter& adapter)
{
WGPUDevice local_device;
WGPURequestDeviceCallbackInfo deviceCallbackInfo = {};
deviceCallbackInfo.callback = handle_request_device;
deviceCallbackInfo.userdata1 = &local_device;
wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
IM_ASSERT(local_device && "Error on Device request");
return local_device;
}
#endif // __EMSCRIPTEN__
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
static bool InitWGPU(SDL_Window* window)
{
WGPUTextureFormat preferred_fmt = WGPUTextureFormat_Undefined; // acquired from SurfaceCapabilities
// Google DAWN backend: Adapter and Device acquisition, Surface creation
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
wgpu::InstanceDescriptor instance_desc = {};
static constexpr wgpu::InstanceFeatureName timedWaitAny = wgpu::InstanceFeatureName::TimedWaitAny;
instance_desc.requiredFeatureCount = 1;
instance_desc.requiredFeatures = &timedWaitAny;
wgpu::Instance instance = wgpu::CreateInstance(&instance_desc);
wgpu::Adapter adapter = RequestAdapter(instance);
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter.Get());
wgpu_device = RequestDevice(instance, adapter);
// Create the surface.
#ifdef __EMSCRIPTEN__
wgpu::EmscriptenSurfaceSourceCanvasHTMLSelector canvas_desc = {};
canvas_desc.selector = "#canvas";
wgpu::SurfaceDescriptor surface_desc = {};
surface_desc.nextInChain = &canvas_desc;
wgpu::Surface surface = instance.CreateSurface(&surface_desc);
#else
wgpu::Surface surface = CreateWGPUSurface(instance.Get(), window);
#endif
if (!surface)
return false;
// Moving Dawn objects into WGPU handles
wgpu_instance = instance.MoveToCHandle();
wgpu_surface = surface.MoveToCHandle();
WGPUSurfaceCapabilities surface_capabilities = {};
wgpuSurfaceGetCapabilities(wgpu_surface, adapter.Get(), &surface_capabilities);
preferred_fmt = surface_capabilities.formats[0];
// WGPU backend: Adapter and Device acquisition, Surface creation
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
wgpu_instance = wgpuCreateInstance(nullptr);
#ifdef __EMSCRIPTEN__
getAdapterAndDeviceViaJS();
wgpu_device = emscripten_webgpu_get_device();
assert(wgpu_device != nullptr && "Error creating the Device");
WGPUSurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
html_surface_desc.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector;
html_surface_desc.selector = "#canvas";
WGPUSurfaceDescriptor surface_desc = {};
surface_desc.nextInChain = &html_surface_desc.chain;
// Create the surface.
wgpu_surface = wgpuInstanceCreateSurface(wgpu_instance, &surface_desc);
preferred_fmt = wgpuSurfaceGetPreferredFormat(wgpu_surface, {} /* adapter */);
#else // __EMSCRIPTEN__
wgpuSetLogCallback(
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
);
wgpuSetLogLevel(WGPULogLevel_Warn);
WGPUAdapter adapter = RequestAdapter(wgpu_instance);
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter);
wgpu_device = RequestDevice(adapter);
// Create the surface.
wgpu_surface = CreateWGPUSurface(wgpu_instance, window);
if (!wgpu_surface)
return false;
WGPUSurfaceCapabilities surface_capabilities = {};
wgpuSurfaceGetCapabilities(wgpu_surface, adapter, &surface_capabilities);
preferred_fmt = surface_capabilities.formats[0];
#endif // __EMSCRIPTEN__
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
wgpu_surface_configuration.presentMode = WGPUPresentMode_Fifo;
wgpu_surface_configuration.alphaMode = WGPUCompositeAlphaMode_Auto;
wgpu_surface_configuration.usage = WGPUTextureUsage_RenderAttachment;
wgpu_surface_configuration.width = wgpu_surface_width;
wgpu_surface_configuration.height = wgpu_surface_height;
wgpu_surface_configuration.device = wgpu_device;
wgpu_surface_configuration.format = preferred_fmt;
wgpuSurfaceConfigure(wgpu_surface, &wgpu_surface_configuration);
wgpu_queue = wgpuDeviceGetQueue(wgpu_device);
return true;
}
// SDL2 helper to create a WebGPU surface (exclusively!) for Native/Desktop applications: available only together with WebGPU/WGPU backend
// As of today (2025/10/31) there is no "official" support in SDL2 to create a surface for WebGPU backend.
// This stub uses "low level" SDL2 calls to acquire information from a specific Window Manager.
// Currently supported platforms: Windows / Linux (X11 and Wayland) / MacOS. Not necessary nor available with EMSCRIPTEN.
#ifndef __EMSCRIPTEN__
#include <SDL_syswm.h>
#undef Status // X11 headers are leaking this and also 'Success', 'Always', 'None', all used in DAWN api. Add #undef if necessary.
WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, SDL_Window* window)
{
SDL_SysWMinfo sysWMInfo;
SDL_VERSION(&sysWMInfo.version);
SDL_GetWindowWMInfo(window, &sysWMInfo);
ImGui_ImplWGPU_CreateSurfaceInfo create_info = {};
create_info.Instance = instance;
#if defined(SDL_VIDEO_DRIVER_COCOA)
{
create_info.System = "cocoa";
create_info.RawWindow = (void*)sysWMInfo.info.cocoa.window;
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
#elif defined(SDL_VIDEO_DRIVER_WAYLAND) || defined(SDL_VIDEO_DRIVER_X11)
const char* sdl_driver = SDL_GetCurrentVideoDriver();
if (sdl_driver && strcmp(sdl_driver, "wayland") == 0)
{
create_info.System = "wayland";
create_info.RawDisplay = (void*)sysWMInfo.info.wl.display;
create_info.RawSurface = (void*)sysWMInfo.info.wl.surface;
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
else
{
create_info.System = "x11";
create_info.RawWindow = (void*)sysWMInfo.info.x11.window;
create_info.RawDisplay = (void*)sysWMInfo.info.x11.display;
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
#elif defined(SDL_VIDEO_DRIVER_WINDOWS)
{
create_info.System = "win32";
create_info.RawWindow = (void*)sysWMInfo.info.win.window;
create_info.RawInstance = (void*)sysWMInfo.info.win.hinstance;
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
#else
#error "Unsupported WebGPU native platform!"
#endif
return nullptr;
}
#endif // #ifndef __EMSCRIPTEN__

View File

@@ -48,7 +48,7 @@ int main(int, char**)
}
SDL_PropertiesID props = SDL_GetWindowProperties(window);
HWND hwnd = (HWND)SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
HWND hwnd = (HWND)SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr);
// Initialize Direct3D
if (!CreateDeviceD3D(hwnd))
@@ -205,6 +205,7 @@ int main(int, char**)
bool CreateDeviceD3D(HWND hWnd)
{
// Setup swap chain
// This is a basic setup. Optimally could use e.g. DXGI_SWAP_EFFECT_FLIP_DISCARD and handle fullscreen mode differently. See #8979 for suggestions.
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 2;

View File

@@ -36,7 +36,7 @@ EMS =
##---------------------------------------------------------------------
# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
EMS += -s USE_SDL=2
EMS += -s USE_SDL=3
EMS += -s DISABLE_EXCEPTION_CATCHING=1
LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1

View File

@@ -51,7 +51,6 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
static ImGui_ImplVulkanH_Window g_MainWindowData;
static uint32_t g_MinImageCount = 2;
static bool g_SwapChainRebuild = false;
static VkImageUsageFlags g_SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
static void check_vk_result(VkResult err)
{
@@ -233,7 +232,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
// Create SwapChain, RenderPass, Framebuffer, etc.
IM_ASSERT(g_MinImageCount >= 2);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, g_SwapChainImageUsage);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, 0);
}
static void CleanupVulkan()
@@ -479,7 +478,7 @@ int main(int, char**)
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
{
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_height, fb_height, g_MinImageCount, g_SwapChainImageUsage);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, 0);
g_MainWindowData.FrameIndex = 0;
g_SwapChainRebuild = false;
}

View File

@@ -0,0 +1,207 @@
# Building for desktop (WebGPU-native) with Dawn:
# 1. git clone https://github.com/google/dawn dawn
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
# 3. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/Debug/example_sdl3_wgpu[.exe]
# * build/example_sdl3_wgpu[.exe]
# Building for desktop (WGPU-Native) with WGPU-Native:
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
# 2. unzip the downloaded file in your_preferred_folder
# 3. cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder ("full path" or "relative" starting from current directory)
# 4. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/Debug/example_sdl3_wgpu[.exe]
# * build/example_sdl3_wgpu[.exe]
# Building for Emscripten:
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
# 2. Install Ninja build system
# 3. emcmake cmake -G Ninja -B build
# (optional) -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py", see ReadMe.md
# 4. cmake --build build
# 5. emrun build/index.html
cmake_minimum_required(VERSION 3.22) # Dawn requires CMake >= 3.22
project(imgui_example_sdl3_wgpu C CXX)
set(IMGUI_EXECUTABLE example_sdl3_wgpu)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
endif()
set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17
# Dear ImGui
set(IMGUI_DIR ../../)
# ImGui example commons source files
set(IMGUI_EXAMPLE_SOURCE_FILES
main.cpp
# backend files
${IMGUI_DIR}/backends/imgui_impl_sdl3.cpp
${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp
# Dear ImGui files
${IMGUI_DIR}/imgui.cpp
${IMGUI_DIR}/imgui_draw.cpp
${IMGUI_DIR}/imgui_demo.cpp
${IMGUI_DIR}/imgui_tables.cpp
${IMGUI_DIR}/imgui_widgets.cpp
)
if(EMSCRIPTEN)
if(EMSCRIPTEN_VERSION VERSION_LESS "4.0.15")
message(FATAL_ERROR "Using Emscripten with SDL3 needs Emscripten version >= 4.0.15")
endif()
if(NOT IMGUI_EMSCRIPTEN_WEBGPU_FLAG) # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG not used, set by current EMSCRIPTEN version
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "4.0.10")
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "--use-port=emdawnwebgpu" CACHE STRING "Choose between --use-port=emdawnwebgpu (Dawn implementation of EMSCRIPTEN) and -sUSE_WEBGPU=1 (WGPU implementation of EMSCRIPTEN, deprecated in 4.0.10): default to --use-port=emdawnwebgpu for EMSCRIPTEN >= 4.0.10")
else()
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "-sUSE_WEBGPU=1" CACHE STRING "Use -sUSE_WEBGPU=1 for EMSCRIPTEN WGPU implementation")
endif()
else() # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG used, check correct version
if(EMSCRIPTEN_VERSION VERSION_LESS "4.0.10" AND "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
# it's necessary EMSCRIPTEN >= v4.0.10 (although "--use-port=path/to/emdawnwebgpu.port.py" is supported/tested from v4.0.8)
message(FATAL_ERROR "emdawnwebgpu needs EMSCRIPTEN version >= 4.0.10")
endif()
endif()
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
else() # Native/Desktop build
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR) # if it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR must be specified
message(FATAL_ERROR "Please specify the Dawn or WGPU base directory")
endif()
if(IMGUI_DAWN_DIR AND IMGUI_WGPU_DIR) # both IMGUI_DAWN_DIR and IMGUI_WGPU_DIR cannot be set
message(FATAL_ERROR "Please specify only one between Dawn / WGPU base directory")
endif()
if(APPLE) # Add SDL3 module to get Surface, with libs and file property for MacOS build
set_source_files_properties(${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++")
set(OS_LIBRARIES "-framework CoreFoundation -framework QuartzCore -framework Metal -framework MetalKit -framework Cocoa")
endif()
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)
if(IMGUI_DAWN_DIR) # DAWN-Native build options
list(APPEND CMAKE_PREFIX_PATH ${IMGUI_DAWN_DIR})
find_package(Threads) # required from Dawn installation
find_package(Dawn) # Search for a Dawn installation using IMGUI_DAWN_DIR in CMAKE_PREFIX_PATH
if(Dawn_FOUND)
message("Dawn Installation has been found!")
set(LIBRARIES dawn::webgpu_dawn ${OS_LIBRARIES})
else()
set(IMGUI_DAWN_DIR CACHE PATH "Path to Dawn repository")
option(DAWN_USE_GLFW OFF) # disable buildin GLFW in DAWN when we use SDL2 / SDL3
option(DAWN_FETCH_DEPENDENCIES "Use fetch_dawn_dependencies.py as an alternative to using depot_tools" ON)
set(DAWN_BUILD_MONOLITHIC_LIBRARY "STATIC" CACHE STRING "Build monolithic library: SHARED, STATIC, or OFF.")
# Dawn builds many things by default - disable things we don't need
option(DAWN_BUILD_SAMPLES "Enables building Dawn's samples" OFF)
option(TINT_BUILD_CMD_TOOLS "Build the Tint command line tools" OFF)
option(TINT_BUILD_DOCS "Build documentation" OFF)
option(TINT_BUILD_TESTS "Build tests" OFF)
if(NOT APPLE)
option(TINT_BUILD_MSL_WRITER "Build the MSL output writer" OFF)
endif()
if(WIN32)
option(DAWN_FORCE_SYSTEM_COMPONENT_LOAD "Allow system component fallback" ON)
option(TINT_BUILD_SPV_READER "Build the SPIR-V input reader" OFF)
option(TINT_BUILD_WGSL_READER "Build the WGSL input reader" ON)
option(TINT_BUILD_GLSL_WRITER "Build the GLSL output writer" OFF)
option(TINT_BUILD_GLSL_VALIDATOR "Build the GLSL output validator" OFF)
option(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" ON)
option(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON)
endif()
# check if WAYLAND is the current Session Type and enable DAWN_USE_WAYLAND Wayland option @compile time
# You can override this using: cmake -DDAWN_USE_WAYLAND=X (X = ON | OFF)
if(LINUX)
if($ENV{XDG_SESSION_TYPE} MATCHES wayland)
option(DAWN_USE_WAYLAND "Enable support for Wayland surface" ON)
endif()
endif()
add_subdirectory("${IMGUI_DAWN_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/dawn" EXCLUDE_FROM_ALL)
set(LIBRARIES webgpu_dawn ${OS_LIBRARIES})
endif()
else() # WGPU-Native build options
set(WGPU_NATIVE_LIB_DIR ${IMGUI_WGPU_DIR}/lib)
find_library(WGPU_LIBRARY NAMES libwgpu_native.a wgpu_native.lib wgpu_native HINTS ${WGPU_NATIVE_LIB_DIR} REQUIRED)
if(WIN32)
set(OS_LIBRARIES d3dcompiler ws2_32 userenv bcrypt ntdll opengl32 Propsys RuntimeObject)
elseif(UNIX AND NOT APPLE)
set(OS_LIBRARIES "-lm -ldl")
endif()
set(LIBRARIES ${WGPU_LIBRARY} ${OS_LIBRARIES})
endif()
endif()
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC
${IMGUI_DIR}
${IMGUI_DIR}/backends
${SDL3_INCLUDE_DIRS}
)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_EXAMPLE_SDL3_WGPU")
# Enable warning level compiler option only for IMGUI_EXAMPLE_SOURCE_FILES
if (MSVC)
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /W4) # warning level 4
else()
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC -Wall) # -Wextra -Wpedantic
endif()
# IMGUI_IMPL_WEBGPU_BACKEND_DAWN/WGPU internal define is set according to:
# EMSCRIPTEN: by used FLAG
# --use-port=emdawnwebgpu --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled (+EMSCRIPTEN)
# -sUSE_WEBGPU=1 --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU enabled (+EMSCRIPTEN)
# NATIVE: by used SDK installation directory
# if IMGUI_DAWN_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled
# if IMGUI_WGPU_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU enabled
if(NOT EMSCRIPTEN) # WegGPU-Native settings
if(IMGUI_DAWN_DIR)
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
if(NOT Dawn_FOUND)
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp)
endif()
else()
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
endif()
target_link_libraries(${IMGUI_EXECUTABLE} PUBLIC ${LIBRARIES} SDL3::SDL3)
else() # Emscripten settings
set(CMAKE_EXECUTABLE_SUFFIX ".html")
if("${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}")
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
else()
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
endif()
message(STATUS "Using ${IMGUI_EMSCRIPTEN_WEBGPU_FLAG} WebGPU implementation")
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "-sUSE_SDL=3")
target_link_options(${IMGUI_EXECUTABLE} PRIVATE
"${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}"
"-sUSE_SDL=3"
"-sWASM=1"
"-sASYNCIFY=1"
"-sALLOW_MEMORY_GROWTH=1"
"-sNO_EXIT_RUNTIME=0"
"-sASSERTIONS=1"
"-sDISABLE_EXCEPTION_CATCHING=1"
# "-sNO_FILESYSTEM=1"
"--shell-file=${CMAKE_CURRENT_LIST_DIR}/../libs/emscripten/shell_minimal.html"
)
set_target_properties(${IMGUI_EXECUTABLE} PROPERTIES OUTPUT_NAME "index")
endif()

View File

@@ -0,0 +1,103 @@
#
# Makefile to use with emscripten
# See https://emscripten.org/docs/getting_started/downloads.html
# for installation instructions.
#
# This Makefile assumes you have loaded emscripten's environment.
# (On Windows, you may need to execute emsdk_env.bat or encmdprompt.bat ahead)
#
# Running `make -f Makefile.emscripten` will produce three files:
# - web/index.html
# - web/index.js
# - web/index.wasm
#
# All three are needed to run the demo.
CC = emcc
CXX = em++
WEB_DIR = web
EXE = $(WEB_DIR)/index.html
IMGUI_DIR = ../..
SOURCES = main.cpp
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl3.cpp $(IMGUI_DIR)/backends/imgui_impl_wgpu.cpp
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
CPPFLAGS =
LDFLAGS =
EMS =
##---------------------------------------------------------------------
## EMSCRIPTEN OPTIONS
##---------------------------------------------------------------------
# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
EMS += -s USE_SDL=3
EMS += -s DISABLE_EXCEPTION_CATCHING=1
LDFLAGS += -s WASM=1
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
LDFLAGS += -s ASYNCIFY=1
LDFLAGS += -s NO_EXIT_RUNTIME=0
LDFLAGS += -s ASSERTIONS=1
# (1) Using legacy WebGPU implementation (Emscripten < 4.0.10)
#EMS += -DIMGUI_IMPL_WEBGPU_BACKEND_WGPU
#LDFLAGS += -s USE_WEBGPU=1
# or (2) Using newer Dawn-based WebGPU port (Emscripten >= 4.0.10)
EMS += --use-port=emdawnwebgpu
LDFLAGS += --use-port=emdawnwebgpu
# Build as single file (binary text encoded in .html file)
#LDFLAGS += -sSINGLE_FILE
# Emscripten allows preloading a file or folder to be accessible at runtime.
# The Makefile for this example project suggests embedding the misc/fonts/ folder into our application, it will then be accessible as "/fonts"
# See documentation for more details: https://emscripten.org/docs/porting/files/packaging_files.html
# (Default value is 0. Set to 1 to enable file-system and include the misc/fonts/ folder as part of the build.)
USE_FILE_SYSTEM ?= 0
ifeq ($(USE_FILE_SYSTEM), 0)
LDFLAGS += -s NO_FILESYSTEM=1
CPPFLAGS += -DIMGUI_DISABLE_FILE_FUNCTIONS
endif
ifeq ($(USE_FILE_SYSTEM), 1)
LDFLAGS += --no-heap-copy --preload-file ../../misc/fonts@/fonts
endif
##---------------------------------------------------------------------
## FINAL BUILD FLAGS
##---------------------------------------------------------------------
CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
#CPPFLAGS += -g
CPPFLAGS += -Wall -Wformat -Os $(EMS)
LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html
LDFLAGS += $(EMS)
##---------------------------------------------------------------------
## BUILD RULES
##---------------------------------------------------------------------
%.o:%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/backends/%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
all: $(EXE)
@echo Build complete for $(EXE)
$(WEB_DIR):
mkdir $@
serve: all
python3 -m http.server -d $(WEB_DIR)
$(EXE): $(OBJS) $(WEB_DIR)
$(CXX) -o $@ $(OBJS) $(LDFLAGS)
clean:
rm -f $(EXE) $(OBJS) $(WEB_DIR)/*.js $(WEB_DIR)/*.wasm $(WEB_DIR)/*.wasm.pre

View File

@@ -0,0 +1,167 @@
## How to Build
---
### Using CMake
#### Building for desktop (WebGPU-native) with Google Dawn:
1. `git clone https://github.com/google/dawn dawn`
2. `cmake -B build -DIMGUI_DAWN_DIR=dawn`
3. `cmake --build build`
The resulting binary will be found at one of the following locations:
* build/Debug/example_sdl3_wgpu[.exe]
* build/example_sdl3_wgpu[.exe]
#### Building for desktop (WebGPU-Native) with WGPU:
1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
2. unzip the downloaded file in `your_preferred_folder`
3. `cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder` ("full path" or "relative" starting from current directory)
5. `cmake --build build`
The resulting binary will be found at one of the following locations:
* build/Debug/example_sdl3_wgpu[.exe]
* build/example_sdl3_wgpu[.exe]
#### Building for Emscripten:
1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
2. Install Ninja build system
3. `emcmake cmake -G Ninja -B build`
- (optional) `-DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py"`, see below
4. `cmake --build build`
#### Sync Emscripten with latest Google Dawn:
If you want to sync Emscripten with latest DAWN release it's necessary to download the `port-emdawnwgpu-package` (released daily by Google) here:
https://github.com/google/dawn/releases
Unpack it in your preferred folder and to replace the step 3 with:
3. `emcmake cmake -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py" -G Ninja -B build`
**N.B.**
For the WASM code produced by Emscripten to work correctly, it will also be necessary to have the "corresponding" (or newer) version of Google Canary (nightly build for developers) that includes the latest changes
---
### CMake by step
#### Generate Dawn Native:
- `cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir -B where_to_build_dir`
- Using `IMGUI_DAWN_DIR` set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
#### Generate WGPU Native:
- `cmake -G Ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -B where_to_build_dir`
- Using `IMGUI_WGPU_DIR` set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
#### Generate Emscripten:
- `emcmake cmake -G Ninja -B where_to_build_dir`\
CMake checks the EMSCRIPEN version then:
- if EMS >= 4.0.10 uses `--use-port=emdawnwebgpu` flag to build
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
- if EMS < 4.0.10 uses `-sUSE_WEBGPU=1` flag to build
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
#### Generate Emscripten forcing `-sUSE_WEBGPU=1` deprecated flag even with EMS >= 4.0.10
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="-sUSE_WEBGPU=1" -B where_to_build_dir`
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
#### Generate Emscripten using external WebGPU library (emdawnwebgpu_pkg)
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path_to_emdawnwebgpu_pkg" -B where_to_build_dir`
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
- *To use external WebGPU library it's necessary to have EMS >= 4.0.10 or the minimum requirements specified by the package:*
- https://github.com/google/dawn/releases
#### Build time
Once the procedure for the specific builder is generated, the build command is **always the same**:
- Build using CMake
- `cmake --build where_to_build_dir`
- It will use selected builder to build the example.
- Build explicitly:
- `cd where_to_build_dir`
- `ninja`
- This is the builder chosen during the generation phase
---
### CMake useful options
#### Generator types (alternative to **ninja** bulder):
- `-G Ninja` to build with __ninja__ builder
- `-G "Unix Makefiles"` to build with __make__ builder
- `-G "Visual Studio 17 2022" -A x64` to create a VS 2022 solution (.sln) file, Windows only
- **Native build only**
- Not **officially** supported to build Google Dawn
Example:
- using **make** instead **ninja**:
- `cmake -G "Unix Makefiles" -DIMGUI_DAWN_DIR=path_to_sdk_dir -B where_to_build_dir`
**Syntax is case sensitive and the "" are necessary in case of spaces between words*
#### Directories
- The directory path can be absolute or relative (starting from the current directory)
- It's necessary to use different `where_to_build_dir` for different CMake generations
#### Build type
The default build type is **Debug**
It is possible to use a different build type using:
- `-DCMAKE_BUILD_TYPE=Release`
- `-DCMAKE_BUILD_TYPE=MinSizeRel`
- `-DCMAKE_BUILD_TYPE=RelWithDebInfo`
Example:
- building **Release**:
- `cmake -G ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -DCMAKE_BUILD_TYPE=Release -B where_to_build_dir `
#### GLFW / SDL2 / SDL3 includes, libraries, search paths and package manager
Includes and libraries, by default, are searched in system/compiler paths (environment variables): you can add the path to your development tools to the environment variables without having to modify the `CMakeLists.txt` file.
- e.g. CLang search in path specified from the following environment variables:
- include files: CPATH, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH
- library files: LIBRARY_PATH
If you are using a package manager (**vcpkg** / **conan** / ... ) you need/can to specify it, adding to cmake command:
- `-DCMAKE_TOOLCHAIN_FILE=path/to/package_manager.cmake`
Examples:
- using **vcpkg** package manager it's necessary adding:
- `-DCMAKE_TOOLCHAIN_FILE=<vcpkg_root_dir>/scripts/buildsystems/vcpkg.cmake`
- full cmake command using **vcpkg** package manager:
- `cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir -DCMAKE_TOOLCHAIN_FILE=<vcpkg_root_dir>/scripts/buildsystems/vcpkg.cmake -B where_to_build_dir`
---
### Using makefile
- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
- Depending on your configuration, in Windows you may need to run `emsdk/emsdk_env.bat` in your console to access the Emscripten command-line tools.
- You may also refer to our [Continuous Integration setup](https://github.com/ocornut/imgui/tree/master/.github/workflows) for Emscripten setup.
- Then build using `make -f Makefile.emscripten` while in the `example_glfw_wgpu/` directory.
- Requires recent Emscripten as WGPU is still a work-in-progress API.
---
## How to Run
To run on a local machine:
- Make sure your browse supports WGPU and it is enabled. WGPU is still WIP not enabled by default in most browser.
- `make serve` will use Python3 to spawn a local webserver, you can then browse http://localhost:8000 to access your build.
- Otherwise, generally you will need a local webserver:
- Quoting [https://emscripten.org/docs/getting_started](https://emscripten.org/docs/getting_started/Tutorial.html#generating-html):<br>
_"Unfortunately several browsers (including Chrome, Safari, and Internet Explorer) do not support file:// [XHR](https://emscripten.org/docs/site/glossary.html#term-xhr) requests, and cant load extra files needed by the HTML (like a .wasm file, or packaged file data as mentioned lower down). For these browsers youll need to serve the files using a [local webserver](https://emscripten.org/docs/getting_started/FAQ.html#faq-local-webserver) and then open http://localhost:8000/hello.html."_
- Emscripten SDK has a handy `emrun` command: `emrun web/example_glfw_wgpu.html --browser firefox` which will spawn a temporary local webserver (in Firefox). See https://emscripten.org/docs/compiling/Running-html-files-with-emrun.html for details.
- You may use Python 3 builtin webserver: `python -m http.server -d web` (this is what `make serve` uses).
- You may use Python 2 builtin webserver: `cd web && python -m SimpleHTTPServer`.
- If you are accessing the files over a network, certain browsers, such as Firefox, will restrict Gamepad API access to secure contexts only (e.g. https only).

View File

@@ -0,0 +1,553 @@
// Dear ImGui: standalone example application for using SDL3 + WebGPU
// - Emscripten is supported for publishing on web. See https://emscripten.org.
// - Dawn is used as a WebGPU implementation on desktop.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
#include "imgui.h"
#include "imgui_impl_sdl3.h"
#include "imgui_impl_wgpu.h"
#include <stdio.h>
#include <stdlib.h>
#include <SDL3/SDL.h>
// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details.
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <emscripten/html5.h>
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#include <emscripten/html5_webgpu.h>
#endif
#include "../libs/emscripten/emscripten_mainloop_stub.h"
#endif
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
#include <webgpu/webgpu_cpp.h>
#endif
// Data
static WGPUInstance wgpu_instance = nullptr;
static WGPUDevice wgpu_device = nullptr;
static WGPUSurface wgpu_surface = nullptr;
static WGPUQueue wgpu_queue = nullptr;
static WGPUSurfaceConfiguration wgpu_surface_configuration = {};
static int wgpu_surface_width = 1280;
static int wgpu_surface_height = 800;
// Forward declarations
static bool InitWGPU(SDL_Window* window);
static WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, SDL_Window* window);
static void ResizeSurface(int width, int height)
{
wgpu_surface_configuration.width = wgpu_surface_width = width;
wgpu_surface_configuration.height = wgpu_surface_height = height;
wgpuSurfaceConfigure( wgpu_surface, (WGPUSurfaceConfiguration*)&wgpu_surface_configuration );
}
// Main code
int main(int, char**)
{
// Setup SDL
// [If using SDL_MAIN_USE_CALLBACKS: all code below until the main loop starts would likely be your SDL_AppInit() function]
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
{
printf("Error: SDL_Init(): %s\n", SDL_GetError());
return 1;
}
// Create SDL window graphics context
float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE;
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+WebGPU example", wgpu_surface_width, wgpu_surface_height, window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return 1;
}
// Initialize WGPU
InitWGPU(window);
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
// Setup Platform/Renderer backends
ImGui_ImplSDL3_InitForOther(window);
ImGui_ImplWGPU_InitInfo init_info;
init_info.Device = wgpu_device;
init_info.NumFramesInFlight = 3;
init_info.RenderTargetFormat = wgpu_surface_configuration.format;
init_info.DepthStencilFormat = WGPUTextureFormat_Undefined;
ImGui_ImplWGPU_Init(&init_info);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - Read 'docs/FONTS.md' for more instructions and details. If you like the default font but want it to scale better, consider using the 'ProggyVector' from the same author!
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
// - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details.
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
#ifndef IMGUI_DISABLE_FILE_FUNCTIONS
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
//IM_ASSERT(font != nullptr);
#endif
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop
bool done = false;
#ifdef __EMSCRIPTEN__
// For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file.
// You may manually call LoadIniSettingsFromMemory() to load settings from your own storage.
io.IniFilename = nullptr;
EMSCRIPTEN_MAINLOOP_BEGIN
#else
while (!done)
#endif
{
// Poll and handle events (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
// [If using SDL_MAIN_USE_CALLBACKS: call ImGui_ImplSDL3_ProcessEvent() from your SDL_AppEvent() function]
SDL_Event event;
while (SDL_PollEvent(&event))
{
ImGui_ImplSDL3_ProcessEvent(&event);
if (event.type == SDL_EVENT_QUIT)
done = true;
if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window))
done = true;
}
// [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppIterate() function]
// React to changes in screen size
int width, height;
SDL_GetWindowSize(window, &width, &height);
if (width != wgpu_surface_width || height != wgpu_surface_height)
ResizeSurface(width, height);
// Check surface status for error. If texture is not optimal, try to reconfigure the surface.
WGPUSurfaceTexture surface_texture;
wgpuSurfaceGetCurrentTexture(wgpu_surface, &surface_texture);
if (ImGui_ImplWGPU_IsSurfaceStatusError(surface_texture.status))
{
fprintf(stderr, "Unrecoverable Surface Texture status=%#.8x\n", surface_texture.status);
abort();
}
if (ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(surface_texture.status))
{
if (surface_texture.texture)
wgpuTextureRelease(surface_texture.texture);
if (width > 0 && height > 0)
ResizeSurface(width, height);
continue;
}
// Start the Dear ImGui frame
ImGui_ImplWGPU_NewFrame();
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
ImGui::End();
}
// 3. Show another simple window.
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
// Rendering
ImGui::Render();
WGPUTextureViewDescriptor view_desc = {};
view_desc.format = wgpu_surface_configuration.format;
view_desc.dimension = WGPUTextureViewDimension_2D;
view_desc.mipLevelCount = WGPU_MIP_LEVEL_COUNT_UNDEFINED;
view_desc.arrayLayerCount = WGPU_ARRAY_LAYER_COUNT_UNDEFINED;
view_desc.aspect = WGPUTextureAspect_All;
WGPUTextureView texture_view = wgpuTextureCreateView(surface_texture.texture, &view_desc);
WGPURenderPassColorAttachment color_attachments = {};
color_attachments.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
color_attachments.loadOp = WGPULoadOp_Clear;
color_attachments.storeOp = WGPUStoreOp_Store;
color_attachments.clearValue = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
color_attachments.view = texture_view;
WGPURenderPassDescriptor render_pass_desc = {};
render_pass_desc.colorAttachmentCount = 1;
render_pass_desc.colorAttachments = &color_attachments;
render_pass_desc.depthStencilAttachment = nullptr;
WGPUCommandEncoderDescriptor enc_desc = {};
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(wgpu_device, &enc_desc);
WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(encoder, &render_pass_desc);
ImGui_ImplWGPU_RenderDrawData(ImGui::GetDrawData(), pass);
wgpuRenderPassEncoderEnd(pass);
WGPUCommandBufferDescriptor cmd_buffer_desc = {};
WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc);
wgpuQueueSubmit(wgpu_queue, 1, &cmd_buffer);
#ifndef __EMSCRIPTEN__
wgpuSurfacePresent(wgpu_surface);
// Tick needs to be called in Dawn to display validation errors
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
wgpuDeviceTick(wgpu_device);
#endif
#endif
wgpuTextureViewRelease(texture_view);
wgpuRenderPassEncoderRelease(pass);
wgpuCommandEncoderRelease(encoder);
wgpuCommandBufferRelease(cmd_buffer);
}
#ifdef __EMSCRIPTEN__
EMSCRIPTEN_MAINLOOP_END;
#endif
// Cleanup
// [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppQuit() function]
ImGui_ImplWGPU_Shutdown();
ImGui_ImplSDL3_Shutdown();
ImGui::DestroyContext();
wgpuSurfaceUnconfigure(wgpu_surface);
wgpuSurfaceRelease(wgpu_surface);
wgpuQueueRelease(wgpu_queue);
wgpuDeviceRelease(wgpu_device);
wgpuInstanceRelease(wgpu_instance);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
static WGPUAdapter RequestAdapter(wgpu::Instance& instance)
{
wgpu::Adapter acquired_adapter;
wgpu::RequestAdapterOptions adapter_options;
auto onRequestAdapter = [&](wgpu::RequestAdapterStatus status, wgpu::Adapter adapter, wgpu::StringView message)
{
if (status != wgpu::RequestAdapterStatus::Success)
{
printf("Failed to get an adapter: %s\n", message.data);
return;
}
acquired_adapter = std::move(adapter);
};
// Synchronously (wait until) acquire Adapter
wgpu::Future waitAdapterFunc { instance.RequestAdapter(&adapter_options, wgpu::CallbackMode::WaitAnyOnly, onRequestAdapter) };
wgpu::WaitStatus waitStatusAdapter = instance.WaitAny(waitAdapterFunc, UINT64_MAX);
IM_ASSERT(acquired_adapter != nullptr && waitStatusAdapter == wgpu::WaitStatus::Success && "Error on Adapter request");
return acquired_adapter.MoveToCHandle();
}
static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter)
{
// Set device callback functions
wgpu::DeviceDescriptor device_desc;
device_desc.SetDeviceLostCallback(wgpu::CallbackMode::AllowSpontaneous,
[](const wgpu::Device&, wgpu::DeviceLostReason type, wgpu::StringView msg) { fprintf(stderr, "%s error: %s\n", ImGui_ImplWGPU_GetDeviceLostReasonName((WGPUDeviceLostReason)type), msg.data); }
);
device_desc.SetUncapturedErrorCallback(
[](const wgpu::Device&, wgpu::ErrorType type, wgpu::StringView msg) { fprintf(stderr, "%s error: %s\n", ImGui_ImplWGPU_GetErrorTypeName((WGPUErrorType)type), msg.data); }
);
wgpu::Device acquired_device;
auto onRequestDevice = [&](wgpu::RequestDeviceStatus status, wgpu::Device local_device, wgpu::StringView message)
{
if (status != wgpu::RequestDeviceStatus::Success)
{
printf("Failed to get an device: %s\n", message.data);
return;
}
acquired_device = std::move(local_device);
};
// Synchronously (wait until) get Device
wgpu::Future waitDeviceFunc { adapter.RequestDevice(&device_desc, wgpu::CallbackMode::WaitAnyOnly, onRequestDevice) };
wgpu::WaitStatus waitStatusDevice = instance.WaitAny(waitDeviceFunc, UINT64_MAX);
IM_ASSERT(acquired_device != nullptr && waitStatusDevice == wgpu::WaitStatus::Success && "Error on Device request");
return acquired_device.MoveToCHandle();
}
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
#ifdef __EMSCRIPTEN__
// Adapter and device initialization via JS
EM_ASYNC_JS( void, getAdapterAndDeviceViaJS, (),
{
if (!navigator.gpu)
throw Error("WebGPU not supported.");
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
Module.preinitializedWebGPUDevice = device;
} );
#else // __EMSCRIPTEN__
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
{
if (status == WGPURequestAdapterStatus_Success)
{
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
*extAdapter = adapter;
}
else
{
printf("Request_adapter status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
}
}
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
{
if (status == WGPURequestDeviceStatus_Success)
{
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
*extDevice = device;
}
else
{
printf("Request_device status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
}
}
static WGPUAdapter RequestAdapter(WGPUInstance& instance)
{
WGPURequestAdapterOptions adapter_options = {};
WGPUAdapter local_adapter;
WGPURequestAdapterCallbackInfo adapterCallbackInfo = {};
adapterCallbackInfo.callback = handle_request_adapter;
adapterCallbackInfo.userdata1 = &local_adapter;
wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
IM_ASSERT(local_adapter && "Error on Adapter request");
return local_adapter;
}
static WGPUDevice RequestDevice(WGPUAdapter& adapter)
{
WGPUDevice local_device;
WGPURequestDeviceCallbackInfo deviceCallbackInfo = {};
deviceCallbackInfo.callback = handle_request_device;
deviceCallbackInfo.userdata1 = &local_device;
wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
IM_ASSERT(local_device && "Error on Device request");
return local_device;
}
#endif // __EMSCRIPTEN__
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
static bool InitWGPU(SDL_Window* window)
{
WGPUTextureFormat preferred_fmt = WGPUTextureFormat_Undefined; // acquired from SurfaceCapabilities
// Google DAWN backend: Adapter and Device acquisition, Surface creation
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
wgpu::InstanceDescriptor instance_desc = {};
static constexpr wgpu::InstanceFeatureName timedWaitAny = wgpu::InstanceFeatureName::TimedWaitAny;
instance_desc.requiredFeatureCount = 1;
instance_desc.requiredFeatures = &timedWaitAny;
wgpu::Instance instance = wgpu::CreateInstance(&instance_desc);
wgpu::Adapter adapter = RequestAdapter(instance);
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter.Get());
wgpu_device = RequestDevice(instance, adapter);
// Create the surface.
#ifdef __EMSCRIPTEN__
wgpu::EmscriptenSurfaceSourceCanvasHTMLSelector canvas_desc = {};
canvas_desc.selector = "#canvas";
wgpu::SurfaceDescriptor surface_desc = {};
surface_desc.nextInChain = &canvas_desc;
wgpu::Surface surface = instance.CreateSurface(&surface_desc);
#else
wgpu::Surface surface = CreateWGPUSurface(instance.Get(), window);
#endif
if (!surface)
return false;
// Moving Dawn objects into WGPU handles
wgpu_instance = instance.MoveToCHandle();
wgpu_surface = surface.MoveToCHandle();
WGPUSurfaceCapabilities surface_capabilities = {};
wgpuSurfaceGetCapabilities(wgpu_surface, adapter.Get(), &surface_capabilities);
preferred_fmt = surface_capabilities.formats[0];
// WGPU backend: Adapter and Device acquisition, Surface creation
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
wgpu_instance = wgpuCreateInstance(nullptr);
#ifdef __EMSCRIPTEN__
getAdapterAndDeviceViaJS();
wgpu_device = emscripten_webgpu_get_device();
IM_ASSERT(wgpu_device != nullptr && "Error creating the Device");
WGPUSurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
html_surface_desc.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector;
html_surface_desc.selector = "#canvas";
WGPUSurfaceDescriptor surface_desc = {};
surface_desc.nextInChain = &html_surface_desc.chain;
// Create the surface.
wgpu_surface = wgpuInstanceCreateSurface(wgpu_instance, &surface_desc);
preferred_fmt = wgpuSurfaceGetPreferredFormat(wgpu_surface, {} /* adapter */);
#else // __EMSCRIPTEN__
wgpuSetLogCallback(
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
);
wgpuSetLogLevel(WGPULogLevel_Warn);
WGPUAdapter adapter = RequestAdapter(wgpu_instance);
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter);
wgpu_device = RequestDevice(adapter);
// Create the surface.
wgpu_surface = CreateWGPUSurface(wgpu_instance, window);
if (!wgpu_surface)
return false;
WGPUSurfaceCapabilities surface_capabilities = {};
wgpuSurfaceGetCapabilities(wgpu_surface, adapter, &surface_capabilities);
preferred_fmt = surface_capabilities.formats[0];
#endif // __EMSCRIPTEN__
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
wgpu_surface_configuration.presentMode = WGPUPresentMode_Fifo;
wgpu_surface_configuration.alphaMode = WGPUCompositeAlphaMode_Auto;
wgpu_surface_configuration.usage = WGPUTextureUsage_RenderAttachment;
wgpu_surface_configuration.width = wgpu_surface_width;
wgpu_surface_configuration.height = wgpu_surface_height;
wgpu_surface_configuration.device = wgpu_device;
wgpu_surface_configuration.format = preferred_fmt;
wgpuSurfaceConfigure(wgpu_surface, &wgpu_surface_configuration);
wgpu_queue = wgpuDeviceGetQueue(wgpu_device);
return true;
}
// SDL3 helper to create a WebGPU surface (exclusively!) for Native/Desktop applications: available only together with WebGPU/WGPU backend
// As of today (2025/10) there is no "official" support in SDL3 to create a surface for WebGPU backend
// This stub uses "low level" SDL3 calls to acquire information from a specific Window Manager.
// Currently supported platforms: Windows / Linux (X11 and Wayland) / MacOS. Not necessary nor available with EMSCRIPTEN.
#ifndef __EMSCRIPTEN__
#if defined(SDL_PLATFORM_WIN32)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>
#endif
static WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, SDL_Window* window)
{
SDL_PropertiesID propertiesID = SDL_GetWindowProperties(window);
ImGui_ImplWGPU_CreateSurfaceInfo create_info = {};
create_info.Instance = instance;
#if defined(SDL_PLATFORM_MACOS)
{
create_info.System = "cocoa";
create_info.RawWindow = (void*)SDL_GetPointerProperty(propertiesID, SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, NULL);
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
#elif defined(SDL_PLATFORM_LINUX)
if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0)
{
create_info.System = "wayland";
create_info.RawDisplay = (void*)SDL_GetPointerProperty(propertiesID, SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, NULL);
create_info.RawSurface = (void*)SDL_GetPointerProperty(propertiesID, SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, NULL);
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
else if (!SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11"))
{
create_info.System = "x11";
create_info.RawWindow = (void*)SDL_GetNumberProperty(propertiesID, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0);
create_info.RawDisplay = (void*)SDL_GetPointerProperty(propertiesID, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL);
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
#elif defined(SDL_PLATFORM_WIN32)
{
create_info.System = "win32";
create_info.RawWindow = (void*)SDL_GetPointerProperty(propertiesID, SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
create_info.RawInstance = (void*)::GetModuleHandle(NULL);
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
}
#else
#error "Unsupported WebGPU native platform!"
#endif
return nullptr;
}
#endif // #ifndef __EMSCRIPTEN__

View File

@@ -198,6 +198,7 @@ int main(int, char**)
bool CreateDeviceD3D(HWND hWnd)
{
// Setup swap chain
// This is a basic setup. Optimally could use handle fullscreen mode differently. See #8979 for suggestions.
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 2;

View File

@@ -198,6 +198,7 @@ int main(int, char**)
bool CreateDeviceD3D(HWND hWnd)
{
// Setup swap chain
// This is a basic setup. Optimally could use e.g. DXGI_SWAP_EFFECT_FLIP_DISCARD and handle fullscreen mode differently. See #8979 for suggestions.
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 2;

View File

@@ -312,6 +312,7 @@ int main(int, char**)
bool CreateDeviceD3D(HWND hWnd)
{
// Setup swap chain
// This is a basic setup. Optimally could handle fullscreen mode differently. See #8979 for suggestions.
DXGI_SWAP_CHAIN_DESC1 sd;
{
ZeroMemory(&sd, sizeof(sd));
@@ -525,7 +526,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
DXGI_SWAP_CHAIN_DESC1 desc = {};
g_pSwapChain->GetDesc1(&desc);
HRESULT result = g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), desc.Format, desc.Flags);
assert(SUCCEEDED(result) && "Failed to resize swapchain.");
IM_ASSERT(SUCCEEDED(result) && "Failed to resize swapchain.");
CreateRenderTarget();
}
return 0;

View File

@@ -37,7 +37,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
int main(int, char**)
{
// Make process DPI aware and obtain main monitor scale
//ImGui_ImplWin32_EnableDpiAwareness(); // FIXME: This somehow doesn't work in the Win32+OpenGL example. Why?
ImGui_ImplWin32_EnableDpiAwareness();
float main_scale = ImGui_ImplWin32_GetDpiScaleForMonitor(::MonitorFromPoint(POINT{ 0, 0 }, MONITOR_DEFAULTTOPRIMARY));
// Create application window

View File

@@ -47,7 +47,6 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
static ImGui_ImplVulkanH_Window g_MainWindowData;
static uint32_t g_MinImageCount = 2;
static bool g_SwapChainRebuild = false;
static VkImageUsageFlags g_SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
static void check_vk_result(VkResult err)
{
@@ -229,7 +228,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
// Create SwapChain, RenderPass, Framebuffer, etc.
IM_ASSERT(g_MinImageCount >= 2);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, g_SwapChainImageUsage);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, 0);
}
static void CleanupVulkan()
@@ -550,7 +549,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
{
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, g_SwapChainImageUsage);
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, 0);
g_MainWindowData.FrameIndex = 0;
g_SwapChainRebuild = false;
}

View File

@@ -41,6 +41,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_sdlgpu3", "exa
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_directx11", "example_sdl3_directx11\example_sdl3_directx11.vcxproj", "{009DAC16-1A9C-47BE-9770-A30A046E8090}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_null", "example_null\example_null.vcxproj", "{1A0BF63C-18EF-4BAE-A8DA-055481B11F5D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -201,6 +203,14 @@ Global
{009DAC16-1A9C-47BE-9770-A30A046E8090}.Release|Win32.Build.0 = Release|Win32
{009DAC16-1A9C-47BE-9770-A30A046E8090}.Release|x64.ActiveCfg = Release|x64
{009DAC16-1A9C-47BE-9770-A30A046E8090}.Release|x64.Build.0 = Release|x64
{1A0BF63C-18EF-4BAE-A8DA-055481B11F5D}.Debug|Win32.ActiveCfg = Debug|Win32
{1A0BF63C-18EF-4BAE-A8DA-055481B11F5D}.Debug|Win32.Build.0 = Debug|Win32
{1A0BF63C-18EF-4BAE-A8DA-055481B11F5D}.Debug|x64.ActiveCfg = Debug|x64
{1A0BF63C-18EF-4BAE-A8DA-055481B11F5D}.Debug|x64.Build.0 = Debug|x64
{1A0BF63C-18EF-4BAE-A8DA-055481B11F5D}.Release|Win32.ActiveCfg = Release|Win32
{1A0BF63C-18EF-4BAE-A8DA-055481B11F5D}.Release|Win32.Build.0 = Release|Win32
{1A0BF63C-18EF-4BAE-A8DA-055481B11F5D}.Release|x64.ActiveCfg = Release|x64
{1A0BF63C-18EF-4BAE-A8DA-055481B11F5D}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -15,7 +15,8 @@
#pragma once
//---- Define assertion handler. Defaults to calling assert().
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
// - If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
// - Compiling with NDEBUG will usually strip out assert() to nothing, which is NOT recommended because we use asserts to notify of programmer mistakes.
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts

699
imgui.cpp

File diff suppressed because it is too large Load Diff

171
imgui.h
View File

@@ -1,35 +1,36 @@
// dear imgui, v1.92.4
// dear imgui, v1.92.5
// (headers)
// Help:
// - See links below.
// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
// - Read top of imgui.cpp for more details, links and comments.
// - Add '#define IMGUI_DEFINE_MATH_OPERATORS' before including this file (or in imconfig.h) to access courtesy maths operators for ImVec2 and ImVec4.
// - Add '#define IMGUI_DEFINE_MATH_OPERATORS' before including imgui.h (or in imconfig.h) to access courtesy maths operators for ImVec2 and ImVec4.
// Resources:
// - FAQ ........................ https://dearimgui.com/faq (in repository as docs/FAQ.md)
// - Homepage ................... https://github.com/ocornut/imgui
// - Releases & changelog ....... https://github.com/ocornut/imgui/releases
// - Releases & Changelog ....... https://github.com/ocornut/imgui/releases
// - Gallery .................... https://github.com/ocornut/imgui/issues?q=label%3Agallery (please post your screenshots/video there!)
// - Wiki ....................... https://github.com/ocornut/imgui/wiki (lots of good stuff there)
// - Getting Started https://github.com/ocornut/imgui/wiki/Getting-Started (how to integrate in an existing app by adding ~25 lines of code)
// - Third-party Extensions https://github.com/ocornut/imgui/wiki/Useful-Extensions (ImPlot & many more)
// - Bindings/Backends https://github.com/ocornut/imgui/wiki/Bindings (language bindings, backends for various tech/engines)
// - Glossary https://github.com/ocornut/imgui/wiki/Glossary
// - Bindings/Backends https://github.com/ocornut/imgui/wiki/Bindings (language bindings + backends for various tech/engines)
// - Debug Tools https://github.com/ocornut/imgui/wiki/Debug-Tools
// - Glossary https://github.com/ocornut/imgui/wiki/Glossary
// - Software using Dear ImGui https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui
// - Issues & support ........... https://github.com/ocornut/imgui/issues
// - Test Engine & Automation ... https://github.com/ocornut/imgui_test_engine (test suite, test engine to automate your apps)
// - Web version of the Demo .... https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html (w/ source code browser)
// For first-time users having issues compiling/linking/running/loading fonts:
// For FIRST-TIME users having issues compiling/linking/running:
// please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above.
// Everything else should be asked in 'Issues'! We are building a database of cross-linked knowledge there.
// EVERYTHING ELSE should be asked in 'Issues'! We are building a database of cross-linked knowledge there.
// Since 1.92, we encourage font loading questions to also be posted in 'Issues'.
// Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.92.4"
#define IMGUI_VERSION_NUM 19240
#define IMGUI_VERSION "1.92.5"
#define IMGUI_VERSION_NUM 19250
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
@@ -89,12 +90,15 @@ Index of this file:
#endif
// Helper Macros
// (note: compiling with NDEBUG will usually strip out assert() to nothing, which is NOT recommended because we use asserts to notify of programmer mistakes.)
#ifndef IM_ASSERT
#include <assert.h>
#define IM_ASSERT(_EXPR) assert(_EXPR) // You can override the default assert handler by editing imconfig.h
#endif
#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR)))) // Size of a static C-style array. Don't use on pointers!
#define IM_UNUSED(_VAR) ((void)(_VAR)) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds.
#define IM_STRINGIFY_HELPER(_EXPR) #_EXPR
#define IM_STRINGIFY(_EXPR) IM_STRINGIFY_HELPER(_EXPR) // Preprocessor idiom to stringify e.g. an integer or a macro.
// Check that version and structures layouts are matching between compiled imgui code and caller. Read comments above DebugCheckVersionAndDataLayout() for details.
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
@@ -211,9 +215,9 @@ struct ImGuiViewport; // A Platform Window (always only one in 'ma
// Enumerations
// - We don't use strongly typed enums much because they add constraints (can't extend in private code, can't store typed in bit fields, extra casting on iteration)
// - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists!
// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// - 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.
// - In Visual Studio: Ctrl+Comma ("Edit.GoToAll") can follow symbols inside comments, whereas Ctrl+F12 ("Edit.GoToImplementation") cannot.
// - 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.
enum ImGuiDir : int; // -> enum ImGuiDir // Enum: A cardinal direction (Left, Right, Up, Down)
enum ImGuiKey : int; // -> enum ImGuiKey // Enum: A key identifier (ImGuiKey_XXX or ImGuiMod_XXX value)
enum ImGuiMouseSource : int; // -> enum ImGuiMouseSource // Enum; A mouse input source identifier (Mouse, TouchScreen, Pen)
@@ -228,9 +232,9 @@ typedef int ImGuiTableBgTarget; // -> enum ImGuiTableBgTarget_ // Enum: A
// Flags (declared as int to allow using as flags without overhead, and to not pollute the top of this file)
// - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists!
// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// - 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.
// - In Visual Studio: Ctrl+Comma ("Edit.GoToAll") can follow symbols inside comments, whereas Ctrl+F12 ("Edit.GoToImplementation") cannot.
// - 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!
@@ -330,7 +334,7 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE
// - You may decide to store a higher-level structure containing texture, sampler, shader etc. with various
// constructors if you like. You will need to implement ==/!= operators.
// History:
// - In v1.91.4 (2024/10/08): the default type for ImTextureID was changed from 'void*' to 'ImU64'. This allowed backends requirig 64-bit worth of data to build on 32-bit architectures. Use intermediary intptr_t cast and read FAQ if you have casting warnings.
// - In v1.91.4 (2024/10/08): the default type for ImTextureID was changed from 'void*' to 'ImU64'. This allowed backends requiring 64-bit worth of data to build on 32-bit architectures. Use intermediary intptr_t cast and read FAQ if you have casting warnings.
// - In v1.92.0 (2025/06/11): added ImTextureRef which carry either a ImTextureID either a pointer to internal texture atlas. All user facing functions taking ImTextureID changed to ImTextureRef
#ifndef ImTextureID
typedef ImU64 ImTextureID; // Default: store up to 64-bits (any pointer or integer). A majority of backends are ok with that.
@@ -659,13 +663,13 @@ namespace ImGui
IMGUI_API bool Combo(const char* label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int popup_max_height_in_items = -1);
// Widgets: Drag Sliders
// - CTRL+Click on any drag box to turn them into an input box. Manually input values aren't clamped by default and can go off-bounds. Use ImGuiSliderFlags_AlwaysClamp to always clamp.
// - Ctrl+Click on any drag box to turn them into an input box. Manually input values aren't clamped by default and can go off-bounds. Use ImGuiSliderFlags_AlwaysClamp to always clamp.
// - For all the Float2/Float3/Float4/Int2/Int3/Int4 versions of every function, note that a 'float v[X]' function argument is the same as 'float* v',
// the array syntax is just a way to document the number of elements that are expected to be accessible. You can pass address of your first element out of a contiguous set, e.g. &myvector.x
// - Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc.
// - Format string may also be set to NULL or use the default format ("%f" or "%d").
// - Speed are per-pixel of mouse movement (v_speed=0.2f: mouse needs to move by 5 pixels to increase value by 1). For keyboard/gamepad navigation, minimum speed is Max(v_speed, minimum_step_at_given_precision).
// - Use v_min < v_max to clamp edits to given limits. Note that CTRL+Click manual input can override those limits if ImGuiSliderFlags_AlwaysClamp is not used.
// - Use v_min < v_max to clamp edits to given limits. Note that Ctrl+Click manual input can override those limits if ImGuiSliderFlags_AlwaysClamp is not used.
// - Use v_max = FLT_MAX / INT_MAX etc to avoid clamping to a maximum, same with v_min = -FLT_MAX / INT_MIN to avoid clamping to a minimum.
// - We use the same sets of flags for DragXXX() and SliderXXX() functions as the features are the same and it makes it easier to swap them.
// - Legacy: Pre-1.78 there are DragXXX() function signatures that take a final `float power=1.0f' argument instead of the `ImGuiSliderFlags flags=0' argument.
@@ -684,7 +688,7 @@ namespace ImGui
IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, ImGuiSliderFlags flags = 0);
// Widgets: Regular Sliders
// - CTRL+Click on any slider to turn them into an input box. Manually input values aren't clamped by default and can go off-bounds. Use ImGuiSliderFlags_AlwaysClamp to always clamp.
// - Ctrl+Click on any slider to turn them into an input box. Manually input values aren't clamped by default and can go off-bounds. Use ImGuiSliderFlags_AlwaysClamp to always clamp.
// - Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc.
// - Format string may also be set to NULL or use the default format ("%f" or "%d").
// - Legacy: Pre-1.78 there are SliderXXX() function signatures that take a final `float power=1.0f' argument instead of the `ImGuiSliderFlags flags=0' argument.
@@ -705,7 +709,7 @@ namespace ImGui
IMGUI_API bool VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0);
// Widgets: Input with Keyboard
// - If you want to use InputText() with std::string or any custom dynamic string type, see misc/cpp/imgui_stdlib.h and comments in imgui_demo.cpp.
// - If you want to use InputText() with std::string or any custom dynamic string type, use the wrapper in misc/cpp/imgui_stdlib.h/.cpp!
// - Most of the ImGuiInputTextFlags flags are only useful for InputText() and not for InputFloatX, InputIntX, InputDouble etc.
IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
@@ -735,7 +739,7 @@ namespace ImGui
// Widgets: Trees
// - TreeNode functions return true when the node is open, in which case you need to also call TreePop() when you are finished displaying the tree node contents.
IMGUI_API bool TreeNode(const char* label);
IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_FMTARGS(2); // helper variation to easily decorelate the id from the displayed string. Read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet().
IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_FMTARGS(2); // helper variation to easily decorrelate the id from the displayed string. Read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet().
IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_FMTARGS(2); // "
IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args) IM_FMTLIST(2);
IMGUI_API bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args) IM_FMTLIST(2);
@@ -760,7 +764,7 @@ namespace ImGui
IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper.
// Multi-selection system for Selectable(), Checkbox(), TreeNode() functions [BETA]
// - This enables standard multi-selection/range-selection idioms (CTRL+Mouse/Keyboard, SHIFT+Mouse/Keyboard, etc.) in a way that also allow a clipper to be used.
// - This enables standard multi-selection/range-selection idioms (Ctrl+Mouse/Keyboard, Shift+Mouse/Keyboard, etc.) in a way that also allow a clipper to be used.
// - ImGuiSelectionUserData is often used to store your item index within the current view (but may store something else).
// - Read comments near ImGuiMultiSelectIO for instructions/details and see 'Demo->Widgets->Selection State & Multi-Select' for demo.
// - TreeNode() is technically supported but... using this correctly is more complicated. You need some sort of linear/random access to your tree,
@@ -973,7 +977,7 @@ namespace ImGui
// Disabling [BETA API]
// - 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 by exception are opted out of disabling.
// - Tooltips windows are automatically opted out of disabling. Note that IsItemHovered() by default returns false on disabled items, unless using ImGuiHoveredFlags_AllowWhenDisabled.
// - BeginDisabled(false)/EndDisabled() essentially does nothing but is provided to facilitate use of boolean expressions (as a micro-optimization: if you have tens of thousands of BeginDisabled(false)/EndDisabled() pairs, you might want to reformulate your code to avoid making those calls)
IMGUI_API void BeginDisabled(bool disabled = true);
IMGUI_API void EndDisabled();
@@ -1165,7 +1169,7 @@ enum ImGuiWindowFlags_
ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y)
ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x)
ImGuiWindowFlags_NoNavInputs = 1 << 16, // No keyboard/gamepad navigation within the window
ImGuiWindowFlags_NoNavFocus = 1 << 17, // No focusing toward this window with keyboard/gamepad navigation (e.g. skipped by CTRL+TAB)
ImGuiWindowFlags_NoNavFocus = 1 << 17, // No focusing toward this window with keyboard/gamepad navigation (e.g. skipped by Ctrl+Tab)
ImGuiWindowFlags_UnsavedDocument = 1 << 18, // Display a dot next to the title. When used in a tab/docking context, tab is selected when clicking the X + closure is not assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar.
ImGuiWindowFlags_NoNav = ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus,
ImGuiWindowFlags_NoDecoration = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse,
@@ -1180,8 +1184,8 @@ enum ImGuiWindowFlags_
// Obsolete names
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiWindowFlags_NavFlattened = 1 << 29, // Obsoleted in 1.90.9: Use ImGuiChildFlags_NavFlattened in BeginChild() call.
ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 30, // Obsoleted in 1.90.0: Use ImGuiChildFlags_AlwaysUseWindowPadding in BeginChild() call.
//ImGuiWindowFlags_NavFlattened = 1 << 29, // Obsoleted in 1.90.9: moved to ImGuiChildFlags. BeginChild(name, size, 0, ImGuiWindowFlags_NavFlattened) --> BeginChild(name, size, ImGuiChildFlags_NavFlattened, 0)
//ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 30, // Obsoleted in 1.90.0: moved to ImGuiChildFlags. BeginChild(name, size, 0, ImGuiWindowFlags_AlwaysUseWindowPadding) --> BeginChild(name, size, ImGuiChildFlags_AlwaysUseWindowPadding, 0)
#endif
};
@@ -1209,7 +1213,7 @@ enum ImGuiChildFlags_
// Obsolete names
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiChildFlags_Border = ImGuiChildFlags_Borders, // Renamed in 1.91.1 (August 2024) for consistency.
//ImGuiChildFlags_Border = ImGuiChildFlags_Borders, // Renamed in 1.91.1 (August 2024) for consistency.
#endif
};
@@ -1272,7 +1276,7 @@ enum ImGuiInputTextFlags_
// - It is much slower than regular text fields.
// Ballpark estimate of cost on my 2019 desktop PC: for a 100 KB text buffer: +~0.3 ms (Optimized) / +~1.0 ms (Debug build).
// The CPU cost is very roughly proportional to text length, so a 10 KB buffer should cost about ten times less.
ImGuiInputTextFlags_WordWrap = 1 << 24, // InputTextMultine(): word-wrap lines that are too long.
ImGuiInputTextFlags_WordWrap = 1 << 24, // InputTextMultiline(): word-wrap lines that are too long.
// Obsolete names
//ImGuiInputTextFlags_AlwaysInsertMode = ImGuiInputTextFlags_AlwaysOverwrite // [renamed in 1.82] name was not matching behavior
@@ -1299,7 +1303,7 @@ enum ImGuiTreeNodeFlags_
ImGuiTreeNodeFlags_SpanAllColumns = 1 << 14, // Frame will span all columns of its container table (label will still fit in current column)
ImGuiTreeNodeFlags_LabelSpanAllColumns = 1 << 15, // Label will span all columns of its container table
//ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 16, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible
ImGuiTreeNodeFlags_NavLeftJumpsToParent = 1 << 17, // Nav: left arrow moves back to parent. This is processed in TreePop() when there's an unfullfilled Left nav request remaining.
ImGuiTreeNodeFlags_NavLeftJumpsToParent = 1 << 17, // Nav: left arrow moves back to parent. This is processed in TreePop() when there's an unfulfilled Left nav request remaining.
ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog,
// [EXPERIMENTAL] Draw lines connecting TreeNode hierarchy. Discuss in GitHub issue #2920.
@@ -1449,7 +1453,7 @@ enum ImGuiHoveredFlags_
// Tooltips mode
// - typically used in IsItemHovered() + SetTooltip() sequence.
// - this is a shortcut to pull flags from 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' where you can reconfigure desired behavior.
// e.g. 'TooltipHoveredFlagsForMouse' defaults to 'ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort'.
// e.g. 'HoverFlagsForTooltipMouse' defaults to 'ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_AllowWhenDisabled'.
// - for frequently actioned or hovered items providing a tooltip, you want may to use ImGuiHoveredFlags_ForTooltip (stationary + delay) so the tooltip doesn't show too often.
// - for items which main purpose is to be hovered, or items with low affordance, or in less consistent apps, prefer no delay or shorter delay.
ImGuiHoveredFlags_ForTooltip = 1 << 12, // Shortcut for standard flags when using IsItemHovered() + SetTooltip() sequence.
@@ -1481,6 +1485,7 @@ enum ImGuiDragDropFlags_
ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, // AcceptDragDropPayload() will returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered.
ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, // Do not draw the default highlight rectangle when hovering over target.
ImGuiDragDropFlags_AcceptNoPreviewTooltip = 1 << 12, // Request hiding the BeginDragDropSource tooltip from the BeginDragDropTarget site.
ImGuiDragDropFlags_AcceptDrawAsHovered = 1 << 13, // Accepting item will render as if hovered. Useful for e.g. a Button() used as a drop target.
ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect, // For peeking ahead and inspecting the payload before delivery.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
@@ -1654,9 +1659,9 @@ enum ImGuiKey : int
ImGuiMod_Mask_ = 0xF000, // 4-bits
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiKey_COUNT = ImGuiKey_NamedKey_END, // Obsoleted in 1.91.5 because it was extremely misleading (since named keys don't start at 0 anymore)
ImGuiKey_COUNT = ImGuiKey_NamedKey_END, // Obsoleted in 1.91.5 because it was misleading (since named keys don't start at 0 anymore)
ImGuiMod_Shortcut = ImGuiMod_Ctrl, // Removed in 1.90.7, you can now simply use ImGuiMod_Ctrl
ImGuiKey_ModCtrl = ImGuiMod_Ctrl, ImGuiKey_ModShift = ImGuiMod_Shift, ImGuiKey_ModAlt = ImGuiMod_Alt, ImGuiKey_ModSuper = ImGuiMod_Super, // Renamed in 1.89
//ImGuiKey_ModCtrl = ImGuiMod_Ctrl, ImGuiKey_ModShift = ImGuiMod_Shift, ImGuiKey_ModAlt = ImGuiMod_Alt, ImGuiKey_ModSuper = ImGuiMod_Super, // Renamed in 1.89
//ImGuiKey_KeyPadEnter = ImGuiKey_KeypadEnter, // Renamed in 1.87
#endif
};
@@ -1678,7 +1683,7 @@ enum ImGuiInputFlags_
ImGuiInputFlags_RouteAlways = 1 << 13, // Do not register route, poll keys directly.
// - Routing options
ImGuiInputFlags_RouteOverFocused = 1 << 14, // Option: global route: higher priority than focused route (unless active item in focused route).
ImGuiInputFlags_RouteOverActive = 1 << 15, // Option: global route: higher priority than active item. Unlikely you need to use that: will interfere with every active items, e.g. CTRL+A registered by InputText will be overridden by this. May not be fully honored as user/internal code is likely to always assume they can access keys when active.
ImGuiInputFlags_RouteOverActive = 1 << 15, // Option: global route: higher priority than active item. Unlikely you need to use that: will interfere with every active items, e.g. Ctrl+A registered by InputText will be overridden by this. May not be fully honored as user/internal code is likely to always assume they can access keys when active.
ImGuiInputFlags_RouteUnlessBgFocused = 1 << 16, // Option: global route: will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications.
ImGuiInputFlags_RouteFromRootWindow = 1 << 17, // Option: route evaluated from the point of view of root window rather than current window.
@@ -1773,11 +1778,12 @@ enum ImGuiCol_
ImGuiCol_TextLink, // Hyperlink color
ImGuiCol_TextSelectedBg, // Selected text inside an InputText
ImGuiCol_TreeLines, // Tree node hierarchy outlines when using ImGuiTreeNodeFlags_DrawLines
ImGuiCol_DragDropTarget, // Rectangle highlighting a drop target
ImGuiCol_DragDropTarget, // Rectangle border highlighting a drop target
ImGuiCol_DragDropTargetBg, // Rectangle background highlighting a drop target
ImGuiCol_UnsavedMarker, // Unsaved Document marker (in window title and tabs)
ImGuiCol_NavCursor, // Color of keyboard/gamepad navigation cursor/rectangle, when visible
ImGuiCol_NavWindowingHighlight, // Highlight window when using CTRL+TAB
ImGuiCol_NavWindowingDimBg, // Darken/colorize entire screen behind the CTRL+TAB window list, when active
ImGuiCol_NavWindowingHighlight, // Highlight window when using Ctrl+Tab
ImGuiCol_NavWindowingDimBg, // Darken/colorize entire screen behind the Ctrl+Tab window list, when active
ImGuiCol_ModalWindowDimBg, // Darken/colorize entire screen behind a modal window, when one is active
ImGuiCol_COUNT,
@@ -1793,9 +1799,9 @@ enum ImGuiCol_
// - The enum only refers to fields of ImGuiStyle which makes sense to be pushed/popped inside UI code.
// During initialization or between frames, feel free to just poke into ImGuiStyle directly.
// - Tip: Use your programming IDE navigation facilities on the names in the _second column_ below to find the actual members and their description.
// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// - 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.
// - In Visual Studio: Ctrl+Comma ("Edit.GoToAll") can follow symbols inside comments, whereas Ctrl+F12 ("Edit.GoToImplementation") cannot.
// - 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.
// - When changing this enum, you need to update the associated internal table GStyleVarInfo[] accordingly. This is where we link enum values to members offset/type.
enum ImGuiStyleVar_
{
@@ -1902,7 +1908,7 @@ enum ImGuiColorEditFlags_
// Obsolete names
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiColorEditFlags_AlphaPreview = 0, // [Removed in 1.91.8] This is the default now. Will display a checkerboard unless ImGuiColorEditFlags_AlphaNoBg is set.
ImGuiColorEditFlags_AlphaPreview = 0, // Removed in 1.91.8. This is the default now. Will display a checkerboard unless ImGuiColorEditFlags_AlphaNoBg is set.
#endif
//ImGuiColorEditFlags_RGB = ImGuiColorEditFlags_DisplayRGB, ImGuiColorEditFlags_HSV = ImGuiColorEditFlags_DisplayHSV, ImGuiColorEditFlags_HEX = ImGuiColorEditFlags_DisplayHex // [renamed in 1.69]
};
@@ -1915,9 +1921,9 @@ enum ImGuiSliderFlags_
ImGuiSliderFlags_None = 0,
ImGuiSliderFlags_Logarithmic = 1 << 5, // Make the widget logarithmic (linear otherwise). Consider using ImGuiSliderFlags_NoRoundToFormat with this if using a format-string with small amount of digits.
ImGuiSliderFlags_NoRoundToFormat = 1 << 6, // Disable rounding underlying value to match precision of the display format string (e.g. %.3f values are rounded to those 3 digits).
ImGuiSliderFlags_NoInput = 1 << 7, // Disable CTRL+Click or Enter key allowing to input text directly into the widget.
ImGuiSliderFlags_NoInput = 1 << 7, // Disable Ctrl+Click or Enter key allowing to input text directly into the widget.
ImGuiSliderFlags_WrapAround = 1 << 8, // Enable wrapping around from max to min and from min to max. Only supported by DragXXX() functions for now.
ImGuiSliderFlags_ClampOnInput = 1 << 9, // Clamp value to min/max bounds when input manually with CTRL+Click. By default CTRL+Click allows going out of bounds.
ImGuiSliderFlags_ClampOnInput = 1 << 9, // Clamp value to min/max bounds when input manually with Ctrl+Click. By default Ctrl+Click allows going out of bounds.
ImGuiSliderFlags_ClampZeroRange = 1 << 10, // Clamp even if min==max==0.0f. Otherwise due to legacy reason DragXXX functions don't clamp with those values. When your clamping limits are dynamic you almost always want to use it.
ImGuiSliderFlags_NoSpeedTweaks = 1 << 11, // Disable keyboard modifiers altering tweak speed. Useful if you want to alter tweak speed yourself based on your own logic.
ImGuiSliderFlags_AlwaysClamp = ImGuiSliderFlags_ClampOnInput | ImGuiSliderFlags_ClampZeroRange,
@@ -2287,7 +2293,7 @@ struct ImGuiStyle
float ColumnsMinSpacing; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1).
float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar.
float ScrollbarRounding; // Radius of grab corners for scrollbar.
float ScrollbarPadding; // Padding of scrollbar grab within its frame (same for both axises).
float ScrollbarPadding; // Padding of scrollbar grab within its frame (same for both axes).
float GrabMinSize; // Minimum width/height of a grab box for slider/scrollbar.
float GrabRounding; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
float LogSliderDeadzone; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero.
@@ -2305,6 +2311,9 @@ struct ImGuiStyle
ImGuiTreeNodeFlags TreeLinesFlags; // Default way to draw lines connecting TreeNode hierarchy. ImGuiTreeNodeFlags_DrawLinesNone or ImGuiTreeNodeFlags_DrawLinesFull or ImGuiTreeNodeFlags_DrawLinesToNodes.
float TreeLinesSize; // Thickness of outlines when using ImGuiTreeNodeFlags_DrawLines.
float TreeLinesRounding; // Radius of lines connecting child nodes to the vertical line.
float DragDropTargetRounding; // Radius of the drag and drop target frame.
float DragDropTargetBorderSize; // Thickness of the drag and drop target border.
float DragDropTargetPadding; // Size to expand the drag and drop target from actual target item size.
ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered).
ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
@@ -2386,7 +2395,7 @@ struct ImGuiIO
// Font system
ImFontAtlas*Fonts; // <auto> // Font atlas: load, rasterize and pack one or more fonts into a single texture.
ImFont* FontDefault; // = NULL // Font to use on NewFrame(). Use NULL to uses Fonts->Fonts[0].
bool FontAllowUserScaling; // = false // [OBSOLETE] Allow user scaling text of individual window with CTRL+Wheel.
bool FontAllowUserScaling; // = false // Allow user scaling text of individual window with Ctrl+Wheel.
// Keyboard/Gamepad Navigation options
bool ConfigNavSwapGamepadButtons; // = false // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout.
@@ -2407,7 +2416,7 @@ struct ImGuiIO
bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
bool ConfigWindowsCopyContentsWithCtrlC; // = false // [EXPERIMENTAL] CTRL+C copy the contents of focused window into the clipboard. Experimental because: (1) has known issues with nested Begin/End pairs (2) text output quality varies (3) text output is in submission order rather than spatial order.
bool ConfigWindowsCopyContentsWithCtrlC; // = false // [EXPERIMENTAL] Ctrl+C copy the contents of focused window into the clipboard. Experimental because: (1) has known issues with nested Begin/End pairs (2) text output quality varies (3) text output is in submission order rather than spatial order.
bool ConfigScrollbarScrollByPage; // = true // Enable scrolling page by page when clicking outside the scrollbar grab. When disabled, always scroll to clicked location. When enabled, Shift+Click scrolls to clicked location.
float ConfigMemoryCompactTimer; // = 60.0f // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable.
@@ -2504,9 +2513,6 @@ struct ImGuiIO
IMGUI_API void ClearEventsQueue(); // Clear all incoming events.
IMGUI_API void ClearInputKeys(); // Clear current keyboard/gamepad state + current frame text input buffer. Equivalent to releasing all keys/buttons.
IMGUI_API void ClearInputMouse(); // Clear current mouse state.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
IMGUI_API void ClearInputCharacters(); // [Obsoleted in 1.89.8] Clear the current frame text input buffer. Now included within ClearInputKeys().
#endif
//------------------------------------------------------------------
// Output - Updated by NewFrame() or EndFrame()/Render()
@@ -2539,7 +2545,7 @@ struct ImGuiIO
// (reading from those variables is fair game, as they are extremely unlikely to be moving anywhere)
ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX, -FLT_MAX) if mouse is unavailable (on another screen, etc.)
bool MouseDown[5]; // Mouse buttons: 0=left, 1=right, 2=middle + extras (ImGuiMouseButton_COUNT == 5). Dear ImGui mostly uses left and right buttons. Other buttons allow us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API.
float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text. >0 scrolls Up, <0 scrolls Down. Hold SHIFT to turn vertical scroll into horizontal scroll.
float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text. >0 scrolls Up, <0 scrolls Down. Hold Shift to turn vertical scroll into horizontal scroll.
float MouseWheelH; // Mouse wheel Horizontal. >0 scrolls Left, <0 scrolls Right. Most users don't have a mouse with a horizontal wheel, may not be filled by all backends.
ImGuiMouseSource MouseSource; // Mouse actual input peripheral (Mouse/TouchScreen/Pen).
bool KeyCtrl; // Keyboard modifier down: Ctrl (non-macOS), Cmd (macOS)
@@ -2562,8 +2568,8 @@ struct ImGuiIO
double MouseReleasedTime[5]; // Time of last released (rarely used! but useful to handle delayed single-click when trying to disambiguate them from double-click).
bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds.
bool MouseDownOwnedUnlessPopupClose[5]; // Track if button was clicked inside a dear imgui window.
bool MouseWheelRequestAxisSwap; // On a non-Mac system, holding SHIFT requests WheelY to perform the equivalent of a WheelX event. On a Mac system this is already enforced by the system.
bool MouseCtrlLeftAsRightClick; // (OSX) Set to true when the current click was a Ctrl+click that spawned a simulated right click
bool MouseWheelRequestAxisSwap; // On a non-Mac system, holding Shift requests WheelY to perform the equivalent of a WheelX event. On a Mac system this is already enforced by the system.
bool MouseCtrlLeftAsRightClick; // (OSX) Set to true when the current click was a Ctrl+Click that spawned a simulated right click
float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked)
float MouseDownDurationPrev[5]; // Previous time the mouse button has been down
float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the clicking point (used for moving thresholds)
@@ -2591,6 +2597,8 @@ struct ImGuiIO
const char* (*GetClipboardTextFn)(void* user_data);
void (*SetClipboardTextFn)(void* user_data, const char* text);
void* ClipboardUserData;
//void ClearInputCharacters() { InputQueueCharacters.resize(0); } // [Obsoleted in 1.89.8] Clear the current frame text input buffer. Now included within ClearInputKeys(). Removed this as it is ambiguous/misleading and generally incorrect to use with the existence of a higher-level input queue.
#endif
IMGUI_API ImGuiIO();
@@ -2949,7 +2957,7 @@ struct ImColor
// Multi-selection system
// Documentation at: https://github.com/ocornut/imgui/wiki/Multi-Select
// - Refer to 'Demo->Widgets->Selection State & Multi-Select' for demos using this.
// - This system implements standard multi-selection idioms (CTRL+Mouse/Keyboard, SHIFT+Mouse/Keyboard, etc)
// - This system implements standard multi-selection idioms (Ctrl+Mouse/Keyboard, Shift+Mouse/Keyboard, etc)
// with support for clipper (skipping non-visible items), box-select and many other details.
// - Selectable(), Checkbox() are supported but custom widgets may use it as well.
// - TreeNode() is technically supported but... using this correctly is more complicated: you need some sort of linear/random access to your tree,
@@ -2987,7 +2995,7 @@ enum ImGuiMultiSelectFlags_
{
ImGuiMultiSelectFlags_None = 0,
ImGuiMultiSelectFlags_SingleSelect = 1 << 0, // Disable selecting more than one item. This is available to allow single-selection code to share same code/logic if desired. It essentially disables the main purpose of BeginMultiSelect() tho!
ImGuiMultiSelectFlags_NoSelectAll = 1 << 1, // Disable CTRL+A shortcut to select all.
ImGuiMultiSelectFlags_NoSelectAll = 1 << 1, // Disable Ctrl+A shortcut to select all.
ImGuiMultiSelectFlags_NoRangeSelect = 1 << 2, // Disable Shift+selection mouse/keyboard support (useful for unordered 2D selection). With BoxSelect is also ensure contiguous SetRange requests are not combined into one. This allows not handling interpolation in SetRange requests.
ImGuiMultiSelectFlags_NoAutoSelect = 1 << 3, // Disable selecting items when navigating (useful for e.g. supporting range-select in a list of checkboxes).
ImGuiMultiSelectFlags_NoAutoClear = 1 << 4, // Disable clearing selection when navigating or selecting another one (generally used with ImGuiMultiSelectFlags_NoAutoSelect. useful for e.g. supporting range-select in a list of checkboxes).
@@ -3003,6 +3011,7 @@ enum ImGuiMultiSelectFlags_
ImGuiMultiSelectFlags_SelectOnClickRelease = 1 << 14, // Apply selection on mouse release when clicking an unselected item. Allow dragging an unselected item without altering selection.
//ImGuiMultiSelectFlags_RangeSelect2d = 1 << 15, // Shift+Selection uses 2d geometry instead of linear sequence, so possible to use Shift+up/down to select vertically in grid. Analogous to what BoxSelect does.
ImGuiMultiSelectFlags_NavWrapX = 1 << 16, // [Temporary] Enable navigation wrapping on X axis. Provided as a convenience because we don't have a design for the general Nav API for this yet. When the more general feature be public we may obsolete this flag in favor of new one.
ImGuiMultiSelectFlags_NoSelectOnRightClick = 1 << 17, // Disable default right-click processing, which selects item on mouse down, and is designed for context-menus.
};
// Main IO structure returned by BeginMultiSelect()/EndMultiSelect().
@@ -3367,8 +3376,8 @@ struct ImDrawList
// Obsolete names
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
inline void PushTextureID(ImTextureRef tex_ref) { PushTexture(tex_ref); } // RENAMED in 1.92.x
inline void PopTextureID() { PopTexture(); } // RENAMED in 1.92.x
inline void PushTextureID(ImTextureRef tex_ref) { PushTexture(tex_ref); } // RENAMED in 1.92.0
inline void PopTextureID() { PopTexture(); } // RENAMED in 1.92.0
#endif
//inline void AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f) { AddEllipse(center, ImVec2(radius_x, radius_y), col, rot, num_segments, thickness); } // OBSOLETED in 1.90.5 (Mar 2024)
//inline void AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0) { AddEllipseFilled(center, ImVec2(radius_x, radius_y), col, rot, num_segments); } // OBSOLETED in 1.90.5 (Mar 2024)
@@ -3405,7 +3414,7 @@ struct ImDrawData
ImVec2 DisplaySize; // Size of the viewport to render (== GetMainViewport()->Size for the main viewport, == io.DisplaySize in most single-viewport applications)
ImVec2 FramebufferScale; // Amount of pixels for each unit of DisplaySize. Copied from viewport->FramebufferScale (== io.DisplayFramebufferScale for main viewport). Generally (1,1) on normal display, (2,2) on OSX with Retina display.
ImGuiViewport* OwnerViewport; // Viewport carrying the ImDrawData instance, might be of use to the renderer (generally not).
ImVector<ImTextureData*>* Textures; // List of textures to update. Most of the times the list is shared by all ImDrawData, has only 1 texture and it doesn't need any update. This almost always points to ImGui::GetPlatformIO().Textures[]. May be overriden or set to NULL if you want to manually update textures.
ImVector<ImTextureData*>* Textures; // List of textures to update. Most of the times the list is shared by all ImDrawData, has only 1 texture and it doesn't need any update. This almost always points to ImGui::GetPlatformIO().Textures[]. May be overridden or set to NULL if you want to manually update textures.
// Functions
ImDrawData() { Clear(); }
@@ -3509,7 +3518,7 @@ struct ImFontConfig
char Name[40]; // <auto> // Name (strictly to ease debugging, hence limited size buffer)
void* FontData; // // TTF/OTF data
int FontDataSize; // // TTF/OTF data size
bool FontDataOwnedByAtlas; // true // TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself).
bool FontDataOwnedByAtlas; // true // TTF/OTF data ownership taken by the owner ImFontAtlas (will delete memory itself).
// Options
bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights.
@@ -3630,7 +3639,7 @@ struct ImFontAtlas
IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter.
IMGUI_API void RemoveFont(ImFont* font);
IMGUI_API void Clear(); // Clear everything (input fonts, output glyphs/textures)
IMGUI_API void Clear(); // Clear everything (input fonts, output glyphs/textures).
IMGUI_API void CompactCache(); // Compact cached glyphs and texture.
IMGUI_API void SetFontLoader(const ImFontLoader* font_loader); // Change font loader at runtime.
@@ -3683,7 +3692,7 @@ struct ImFontAtlas
// Register and retrieve custom rectangles
// - You can request arbitrary rectangles to be packed into the atlas, for your own purpose.
// - Since 1.92.X, packing is done immediately in the function call (previously packing was done during the Build call)
// - Since 1.92.0, packing is done immediately in the function call (previously packing was done during the Build call)
// - You can render your pixels into the texture right after calling the AddCustomRect() functions.
// - VERY IMPORTANT:
// - Texture may be created/resized at any time when calling ImGui or ImFontAtlas functions.
@@ -3722,7 +3731,7 @@ struct ImFontAtlas
#ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImTextureRef TexRef; // Latest texture identifier == TexData->GetTexRef().
#else
union { ImTextureRef TexRef; ImTextureRef TexID; }; // Latest texture identifier == TexData->GetTexRef(). // RENAMED TexID to TexRef in 1.92.x
union { ImTextureRef TexRef; ImTextureRef TexID; }; // Latest texture identifier == TexData->GetTexRef(). // RENAMED TexID to TexRef in 1.92.0.
#endif
ImTextureData* TexData; // Latest texture.
@@ -3752,15 +3761,15 @@ struct ImFontAtlas
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// Legacy: You can request your rectangles to be mapped as font glyph (given a font + Unicode point), so you can render e.g. custom colorful icons and use them as regular glyphs. --> Prefer using a custom ImFontLoader.
ImFontAtlasRect TempRect; // For old GetCustomRectByIndex() API
inline ImFontAtlasRectId AddCustomRectRegular(int w, int h) { return AddCustomRect(w, h); } // RENAMED in 1.92.X
inline const ImFontAtlasRect* GetCustomRectByIndex(ImFontAtlasRectId id) { return GetCustomRect(id, &TempRect) ? &TempRect : NULL; } // OBSOLETED in 1.92.X
inline void CalcCustomRectUV(const ImFontAtlasRect* r, ImVec2* out_uv_min, ImVec2* out_uv_max) const { *out_uv_min = r->uv0; *out_uv_max = r->uv1; } // OBSOLETED in 1.92.X
IMGUI_API ImFontAtlasRectId AddCustomRectFontGlyph(ImFont* font, ImWchar codepoint, int w, int h, float advance_x, const ImVec2& offset = ImVec2(0, 0)); // OBSOLETED in 1.92.X: Use custom ImFontLoader in ImFontConfig
IMGUI_API ImFontAtlasRectId AddCustomRectFontGlyphForSize(ImFont* font, float font_size, ImWchar codepoint, int w, int h, float advance_x, const ImVec2& offset = ImVec2(0, 0)); // ADDED AND OBSOLETED in 1.92.X
inline ImFontAtlasRectId AddCustomRectRegular(int w, int h) { return AddCustomRect(w, h); } // RENAMED in 1.92.0
inline const ImFontAtlasRect* GetCustomRectByIndex(ImFontAtlasRectId id) { return GetCustomRect(id, &TempRect) ? &TempRect : NULL; } // OBSOLETED in 1.92.0
inline void CalcCustomRectUV(const ImFontAtlasRect* r, ImVec2* out_uv_min, ImVec2* out_uv_max) const { *out_uv_min = r->uv0; *out_uv_max = r->uv1; } // OBSOLETED in 1.92.0
IMGUI_API ImFontAtlasRectId AddCustomRectFontGlyph(ImFont* font, ImWchar codepoint, int w, int h, float advance_x, const ImVec2& offset = ImVec2(0, 0)); // OBSOLETED in 1.92.0: Use custom ImFontLoader in ImFontConfig
IMGUI_API ImFontAtlasRectId AddCustomRectFontGlyphForSize(ImFont* font, float font_size, ImWchar codepoint, int w, int h, float advance_x, const ImVec2& offset = ImVec2(0, 0)); // ADDED AND OBSOLETED in 1.92.0
#endif
//unsigned int FontBuilderFlags; // OBSOLETED in 1.92.X: Renamed to FontLoaderFlags.
//int TexDesiredWidth; // OBSOLETED in 1.92.X: Force texture width before calling Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height.
//typedef ImFontAtlasRect ImFontAtlasCustomRect; // OBSOLETED in 1.92.X
//unsigned int FontBuilderFlags; // OBSOLETED in 1.92.0: Renamed to FontLoaderFlags.
//int TexDesiredWidth; // OBSOLETED in 1.92.0: Force texture width before calling Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height.
//typedef ImFontAtlasRect ImFontAtlasCustomRect; // OBSOLETED in 1.92.0
//typedef ImFontAtlasCustomRect CustomRect; // OBSOLETED in 1.72+
//typedef ImFontGlyphRangesBuilder GlyphRangesBuilder; // OBSOLETED in 1.67+
};
@@ -3788,7 +3797,7 @@ struct ImFontBaked
unsigned int LoadNoRenderOnLayout:1;// 0 // // Enable a two-steps mode where CalcTextSize() calls will load AdvanceX *without* rendering/packing glyphs. Only advantagous if you know that the glyph is unlikely to actually be rendered, otherwise it is slower because we'd do one query on the first CalcTextSize and one query on the first Draw.
int LastUsedFrame; // 4 // // Record of that time this was bounds
ImGuiID BakedId; // 4 // // Unique ID for this baked storage
ImFont* ContainerFont; // 4-8 // in // Parent font
ImFont* OwnerFont; // 4-8 // in // Parent font
void* FontLoaderDatas; // 4-8 // // Font loader opaque storage (per baked font * sources): single contiguous buffer allocated by imgui, passed to loader.
// Functions
@@ -3812,14 +3821,14 @@ enum ImFontFlags_
// Font runtime data and rendering
// - ImFontAtlas automatically loads a default embedded font for you if you didn't load one manually.
// - Since 1.92.X a font may be rendered as any size! Therefore a font doesn't have one specific size.
// - Since 1.92.0 a font may be rendered as any size! Therefore a font doesn't have one specific size.
// - Use 'font->GetFontBaked(size)' to retrieve the ImFontBaked* corresponding to a given size.
// - If you used g.Font + g.FontSize (which is frequent from the ImGui layer), you can use g.FontBaked as a shortcut, as g.FontBaked == g.Font->GetFontBaked(g.FontSize).
struct ImFont
{
// [Internal] Members: Hot ~12-20 bytes
ImFontBaked* LastBaked; // 4-8 // Cache last bound baked. NEVER USE DIRECTLY. Use GetFontBaked().
ImFontAtlas* ContainerAtlas; // 4-8 // What we have been loaded into.
ImFontAtlas* OwnerAtlas; // 4-8 // What we have been loaded into.
ImFontFlags Flags; // 4 // Font flags.
float CurrentRasterizerDensity; // Current rasterizer density. This is a varying state of the font.
@@ -3827,7 +3836,7 @@ struct ImFont
// Conceptually Sources[] is the list of font sources merged to create this font.
ImGuiID FontId; // Unique identifier for the font
float LegacySize; // 4 // in // Font size passed to AddFont(). Use for old code calling PushFont() expecting to use that size. (use ImGui::GetFontBaked() to get font baked at current bound size).
ImVector<ImFontConfig*> Sources; // 16 // in // List of sources. Pointers within ContainerAtlas->Sources[]
ImVector<ImFontConfig*> Sources; // 16 // in // List of sources. Pointers within OwnerAtlas->Sources[]
ImWchar EllipsisChar; // 2-4 // out // Character used for ellipsis rendering ('...').
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, 16 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 4K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints.
@@ -3841,7 +3850,7 @@ struct ImFont
IMGUI_API ImFont();
IMGUI_API ~ImFont();
IMGUI_API bool IsGlyphInFont(ImWchar c);
bool IsLoaded() const { return ContainerAtlas != NULL; }
bool IsLoaded() const { return OwnerAtlas != NULL; }
const char* GetDebugName() const { return Sources.Size ? Sources[0]->Name : "<unknown>"; } // Fill ImFontConfig::Name.
// [Internal] Don't use!
@@ -3941,7 +3950,7 @@ struct ImGuiPlatformIO
void* Platform_ClipboardUserData;
// Optional: Open link/folder/file in OS Shell
// (default to use ShellExecuteW() on Windows, system() on Linux/Mac)
// (default to use ShellExecuteW() on Windows, system() on Linux/Mac. expected to return false on failure, but some platforms may always return true)
bool (*Platform_OpenInShellFn)(ImGuiContext* ctx, const char* path);
void* Platform_OpenInShellUserData;
@@ -3978,8 +3987,8 @@ struct ImGuiPlatformIO
// Functions
//------------------------------------------------------------------
void ClearPlatformHandlers(); // Clear all Platform_XXX fields. Typically called on Platform Backend shutdown.
void ClearRendererHandlers(); // Clear all Renderer_XXX fields. Typically called on Renderer Backend shutdown.
IMGUI_API void ClearPlatformHandlers(); // Clear all Platform_XXX fields. Typically called on Platform Backend shutdown.
IMGUI_API void ClearRendererHandlers(); // Clear all Renderer_XXX fields. Typically called on Renderer Backend shutdown.
};
// (Optional) Support for IME (Input Method Editor) via the platform_io.Platform_SetImeDataFn() function. Handler is called during EndFrame().
@@ -4024,10 +4033,10 @@ namespace ImGui
inline void ShowStackToolWindow(bool* p_open = NULL) { ShowIDStackToolWindow(p_open); }
IMGUI_API bool Combo(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int popup_max_height_in_items = -1);
IMGUI_API bool ListBox(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int height_in_items = -1);
// OBSOLETED in 1.89.7 (from June 2023)
IMGUI_API void SetItemAllowOverlap(); // Use SetNextItemAllowOverlap() before item.
// Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE)
// OBSOLETED in 1.89.7 (from June 2023)
//IMGUI_API void SetItemAllowOverlap(); // Use SetNextItemAllowOverlap() _before_ item.
//-- OBSOLETED in 1.89.4 (from March 2023)
//static inline void PushAllowKeyboardFocus(bool tab_stop) { PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop); }
//static inline void PopAllowKeyboardFocus() { PopItemFlag(); }
@@ -4093,7 +4102,7 @@ namespace ImGui
//static inline void SetScrollPosHere() { SetScrollHere(); } // OBSOLETED in 1.42
}
//-- OBSOLETED in 1.92.x: ImFontAtlasCustomRect becomes ImTextureRect
//-- OBSOLETED in 1.92.0: ImFontAtlasCustomRect becomes ImTextureRect
// - ImFontAtlasCustomRect::X,Y --> ImTextureRect::x,y
// - ImFontAtlasCustomRect::Width,Height --> ImTextureRect::w,h
// - ImFontAtlasCustomRect::GlyphColored --> if you need to write to this, instead you can write to 'font->Glyphs.back()->Colored' after calling AddCustomRectFontGlyph()
@@ -4129,7 +4138,7 @@ typedef ImFontAtlasRect ImFontAtlasCustomRect;
//};
// RENAMED and MERGED both ImGuiKey_ModXXX and ImGuiModFlags_XXX into ImGuiMod_XXX (from September 2022)
// RENAMED ImGuiKeyModFlags -> ImGuiModFlags in 1.88 (from April 2022). Exceptionally commented out ahead of obscolescence schedule to reduce confusion and because they were not meant to be used in the first place.
// RENAMED ImGuiKeyModFlags -> ImGuiModFlags in 1.88 (from April 2022). Exceptionally commented out ahead of obsolescence schedule to reduce confusion and because they were not meant to be used in the first place.
//typedef ImGuiKeyChord ImGuiModFlags; // == int. We generally use ImGuiKeyChord to mean "a ImGuiKey or-ed with any number of ImGuiMod_XXX value", so you may store mods in there.
//enum ImGuiModFlags_ { ImGuiModFlags_None = 0, ImGuiModFlags_Ctrl = ImGuiMod_Ctrl, ImGuiModFlags_Shift = ImGuiMod_Shift, ImGuiModFlags_Alt = ImGuiMod_Alt, ImGuiModFlags_Super = ImGuiMod_Super };
//typedef ImGuiKeyChord ImGuiKeyModFlags; // == int

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.92.4
// dear imgui, v1.92.5
// (demo code)
// Help:
@@ -59,9 +59,9 @@
// Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp.
// Navigating this file:
// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// - 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.
// - In Visual Studio: Ctrl+Comma ("Edit.GoToAll") can follow symbols inside comments, whereas Ctrl+F12 ("Edit.GoToImplementation") cannot.
// - 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.
// - You can search/grep for all sections listed in the index to find the section.
/*
@@ -288,7 +288,7 @@ extern ImGuiDemoMarkerCallback GImGuiDemoMarkerCallback;
extern void* GImGuiDemoMarkerCallbackUserData;
ImGuiDemoMarkerCallback GImGuiDemoMarkerCallback = NULL;
void* GImGuiDemoMarkerCallbackUserData = NULL;
#define IMGUI_DEMO_MARKER(section) do { if (GImGuiDemoMarkerCallback != NULL) GImGuiDemoMarkerCallback(__FILE__, __LINE__, section, GImGuiDemoMarkerCallbackUserData); } while (0)
#define IMGUI_DEMO_MARKER(section) do { if (GImGuiDemoMarkerCallback != NULL) GImGuiDemoMarkerCallback("imgui_demo.cpp", __LINE__, section, GImGuiDemoMarkerCallbackUserData); } while (0)
//-----------------------------------------------------------------------------
// [SECTION] Demo Window / ShowDemoWindow()
@@ -510,7 +510,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::SameLine(); HelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback.");
ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly);
ImGui::Checkbox("io.ConfigWindowsCopyContentsWithCtrlC", &io.ConfigWindowsCopyContentsWithCtrlC); // [EXPERIMENTAL]
ImGui::SameLine(); HelpMarker("*EXPERIMENTAL* CTRL+C copy the contents of focused window into the clipboard.\n\nExperimental because:\n- (1) has known issues with nested Begin/End pairs.\n- (2) text output quality varies.\n- (3) text output is in submission order rather than spatial order.");
ImGui::SameLine(); HelpMarker("*EXPERIMENTAL* Ctrl+C copy the contents of focused window into the clipboard.\n\nExperimental because:\n- (1) has known issues with nested Begin/End pairs.\n- (2) text output quality varies.\n- (3) text output is in submission order rather than spatial order.");
ImGui::Checkbox("io.ConfigScrollbarScrollByPage", &io.ConfigScrollbarScrollByPage);
ImGui::SameLine(); HelpMarker("Enable scrolling page by page when clicking outside the scrollbar grab.\nWhen disabled, always scroll to clicked location.\nWhen enabled, Shift+Click scrolls to clicked location.");
@@ -887,19 +887,20 @@ static void DemoWindowWidgetsBasic()
ImGui::SeparatorText("Inputs");
{
// To wire InputText() with std::string or any other custom string type,
// see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file.
// If you want to use InputText() with std::string or any custom dynamic string type:
// - For std::string: use the wrapper in misc/cpp/imgui_stdlib.h/.cpp
// - Otherwise, see the 'Dear ImGui Demo->Widgets->Text Input->Resize Callback' for using ImGuiInputTextFlags_CallbackResize.
IMGUI_DEMO_MARKER("Widgets/Basic/InputText");
static char str0[128] = "Hello, world!";
ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
ImGui::SameLine(); HelpMarker(
"USER:\n"
"Hold SHIFT or use mouse to select text.\n"
"CTRL+Left/Right to word jump.\n"
"CTRL+A or Double-Click to select all.\n"
"CTRL+X,CTRL+C,CTRL+V for clipboard.\n"
"CTRL+Z to undo, CTRL+Y/CTRL+SHIFT+Z to redo.\n"
"ESCAPE to revert.\n\n"
"Hold Shift or use mouse to select text.\n"
"Ctrl+Left/Right to word jump.\n"
"Ctrl+A or Double-Click to select all.\n"
"Ctrl+X,Ctrl+C,Ctrl+V for clipboard.\n"
"Ctrl+Z to undo, Ctrl+Y/Ctrl+Shift+Z to redo.\n"
"Escape to revert.\n\n"
"PROGRAMMER:\n"
"You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() "
"to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated "
@@ -936,8 +937,8 @@ static void DemoWindowWidgetsBasic()
ImGui::DragInt("drag int", &i1, 1);
ImGui::SameLine(); HelpMarker(
"Click and drag to edit value.\n"
"Hold SHIFT/ALT for faster/slower edit.\n"
"Double-click or CTRL+click to input value.");
"Hold Shift/Alt for faster/slower edit.\n"
"Double-Click or Ctrl+Click to input value.");
ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%", ImGuiSliderFlags_AlwaysClamp);
ImGui::DragInt("drag int wrap 100..200", &i3, 1, 100, 200, "%d", ImGuiSliderFlags_WrapAround);
@@ -953,7 +954,7 @@ static void DemoWindowWidgetsBasic()
IMGUI_DEMO_MARKER("Widgets/Basic/SliderInt, SliderFloat");
static int i1 = 0;
ImGui::SliderInt("slider int", &i1, -1, 3);
ImGui::SameLine(); HelpMarker("CTRL+click to input value.");
ImGui::SameLine(); HelpMarker("Ctrl+Click to input value.");
static float f1 = 0.123f, f2 = 0.0f;
ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
@@ -971,7 +972,7 @@ static void DemoWindowWidgetsBasic()
static int elem = Element_Fire;
const char* elems_names[Element_COUNT] = { "Fire", "Earth", "Air", "Water" };
const char* elem_name = (elem >= 0 && elem < Element_COUNT) ? elems_names[elem] : "Unknown";
ImGui::SliderInt("slider enum", &elem, 0, Element_COUNT - 1, elem_name); // Use ImGuiSliderFlags_NoInput flag to disable CTRL+Click here.
ImGui::SliderInt("slider enum", &elem, 0, Element_COUNT - 1, elem_name); // Use ImGuiSliderFlags_NoInput flag to disable Ctrl+Click here.
ImGui::SameLine(); HelpMarker("Using the format string parameter to display a name instead of the underlying integer.");
}
@@ -985,8 +986,8 @@ static void DemoWindowWidgetsBasic()
ImGui::SameLine(); HelpMarker(
"Click on the color square to open a color picker.\n"
"Click and hold to use drag and drop.\n"
"Right-click on the color square to show options.\n"
"CTRL+click on individual component to input value.\n");
"Right-Click on the color square to show options.\n"
"Ctrl+Click on individual component to input value.\n");
ImGui::ColorEdit4("color 2", col2);
}
@@ -1104,7 +1105,7 @@ static void DemoWindowWidgetsColorAndPickers()
ImGui::Text("Color widget:");
ImGui::SameLine(); HelpMarker(
"Click on the color square to open a color picker.\n"
"CTRL+click on individual component to input value.\n");
"Ctrl+Click on individual component to input value.\n");
ImGui::ColorEdit3("MyColor##1", (float*)&color, base_flags);
IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit (HSV, with Alpha)");
@@ -1436,7 +1437,7 @@ static void DemoWindowWidgetsDataTypes()
ImGui::Checkbox("Clamp integers to 0..50", &drag_clamp);
ImGui::SameLine(); HelpMarker(
"As with every widget in dear imgui, we never modify values unless there is a user interaction.\n"
"You can override the clamping limits by using CTRL+Click to input a value.");
"You can override the clamping limits by using Ctrl+Click to input a value.");
ImGui::DragScalar("drag s8", ImGuiDataType_S8, &s8_v, drag_speed, drag_clamp ? &s8_zero : NULL, drag_clamp ? &s8_fifty : NULL);
ImGui::DragScalar("drag u8", ImGuiDataType_U8, &u8_v, drag_speed, drag_clamp ? &u8_zero : NULL, drag_clamp ? &u8_fifty : NULL, "%u ms");
ImGui::DragScalar("drag s16", ImGuiDataType_S16, &s16_v, drag_speed, drag_clamp ? &s16_zero : NULL, drag_clamp ? &s16_fifty : NULL);
@@ -1696,7 +1697,7 @@ static void DemoWindowWidgetsDragsAndSliders()
static ImGuiSliderFlags flags = ImGuiSliderFlags_None;
ImGui::CheckboxFlags("ImGuiSliderFlags_AlwaysClamp", &flags, ImGuiSliderFlags_AlwaysClamp);
ImGui::CheckboxFlags("ImGuiSliderFlags_ClampOnInput", &flags, ImGuiSliderFlags_ClampOnInput);
ImGui::SameLine(); HelpMarker("Clamp value to min/max bounds when input manually with CTRL+Click. By default CTRL+Click allows going out of bounds.");
ImGui::SameLine(); HelpMarker("Clamp value to min/max bounds when input manually with Ctrl+Click. By default Ctrl+Click allows going out of bounds.");
ImGui::CheckboxFlags("ImGuiSliderFlags_ClampZeroRange", &flags, ImGuiSliderFlags_ClampZeroRange);
ImGui::SameLine(); HelpMarker("Clamp even if min==max==0.0f. Otherwise DragXXX functions don't clamp.");
ImGui::CheckboxFlags("ImGuiSliderFlags_Logarithmic", &flags, ImGuiSliderFlags_Logarithmic);
@@ -1704,7 +1705,7 @@ static void DemoWindowWidgetsDragsAndSliders()
ImGui::CheckboxFlags("ImGuiSliderFlags_NoRoundToFormat", &flags, ImGuiSliderFlags_NoRoundToFormat);
ImGui::SameLine(); HelpMarker("Disable rounding underlying value to match precision of the format string (e.g. %.3f values are rounded to those 3 digits).");
ImGui::CheckboxFlags("ImGuiSliderFlags_NoInput", &flags, ImGuiSliderFlags_NoInput);
ImGui::SameLine(); HelpMarker("Disable CTRL+Click or Enter key allowing to input text directly into the widget.");
ImGui::SameLine(); HelpMarker("Disable Ctrl+Click or Enter key allowing to input text directly into the widget.");
ImGui::CheckboxFlags("ImGuiSliderFlags_NoSpeedTweaks", &flags, ImGuiSliderFlags_NoSpeedTweaks);
ImGui::SameLine(); HelpMarker("Disable keyboard modifiers altering tweak speed. Useful if you want to alter tweak speed yourself based on your own logic.");
ImGui::CheckboxFlags("ImGuiSliderFlags_WrapAround", &flags, ImGuiSliderFlags_WrapAround);
@@ -2647,6 +2648,10 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d
{
HelpMarker("Selections can be built using Selectable(), TreeNode() or other widgets. Selection state is owned by application code/data.");
ImGui::BulletText("Wiki page:");
ImGui::SameLine();
ImGui::TextLinkOpenURL("imgui/wiki/Multi-Select", "https://github.com/ocornut/imgui/wiki/Multi-Select");
// Without any fancy API: manage single-selection yourself.
IMGUI_DEMO_MARKER("Widgets/Selection State/Single-Select");
if (ImGui::TreeNode("Single-Select"))
@@ -2663,11 +2668,11 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d
}
// Demonstrate implementation a most-basic form of multi-selection manually
// This doesn't support the SHIFT modifier which requires BeginMultiSelect()!
// This doesn't support the Shift modifier which requires BeginMultiSelect()!
IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (manual/simplified, without BeginMultiSelect)");
if (ImGui::TreeNode("Multi-Select (manual/simplified, without BeginMultiSelect)"))
{
HelpMarker("Hold CTRL and click to select multiple items.");
HelpMarker("Hold Ctrl and Click to select multiple items.");
static bool selection[5] = { false, false, false, false, false };
for (int n = 0; n < 5; n++)
{
@@ -2675,7 +2680,7 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d
sprintf(buf, "Object %d", n);
if (ImGui::Selectable(buf, selection[n]))
{
if (!ImGui::GetIO().KeyCtrl) // Clear selection when CTRL is not held
if (!ImGui::GetIO().KeyCtrl) // Clear selection when Ctrl is not held
memset(selection, 0, sizeof(selection));
selection[n] ^= 1; // Toggle current item
}
@@ -2684,7 +2689,7 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d
}
// Demonstrate handling proper multi-selection using the BeginMultiSelect/EndMultiSelect API.
// SHIFT+Click w/ CTRL and other standard features are supported.
// Shift+Click w/ Ctrl and other standard features are supported.
// We use the ImGuiSelectionBasicStorage helper which you may freely reimplement.
IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select");
if (ImGui::TreeNode("Multi-Select"))
@@ -2693,7 +2698,7 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d
ImGui::BulletText("Keyboard navigation (arrows, page up/down, home/end, space).");
ImGui::BulletText("Ctrl modifier to preserve and toggle selection.");
ImGui::BulletText("Shift modifier for range selection.");
ImGui::BulletText("CTRL+A to select all.");
ImGui::BulletText("Ctrl+A to select all.");
ImGui::BulletText("Escape to clear selection.");
ImGui::BulletText("Click and drag to box-select.");
ImGui::Text("Tip: Use 'Demo->Tools->Debug Log->Selection' to see selection requests as they happen.");
@@ -3180,6 +3185,7 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoSelect", &flags, ImGuiMultiSelectFlags_NoAutoSelect);
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClear", &flags, ImGuiMultiSelectFlags_NoAutoClear);
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClearOnReselect", &flags, ImGuiMultiSelectFlags_NoAutoClearOnReselect);
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoSelectOnRightClick", &flags, ImGuiMultiSelectFlags_NoSelectOnRightClick);
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect1d", &flags, ImGuiMultiSelectFlags_BoxSelect1d);
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect2d", &flags, ImGuiMultiSelectFlags_BoxSelect2d);
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelectNoScroll", &flags, ImGuiMultiSelectFlags_BoxSelectNoScroll);
@@ -3691,8 +3697,10 @@ static void DemoWindowWidgetsTextInput()
IMGUI_DEMO_MARKER("Widgets/Text Input/Multi-line Text Input");
if (ImGui::TreeNode("Multi-line Text Input"))
{
// Note: we are using a fixed-sized buffer for simplicity here. See ImGuiInputTextFlags_CallbackResize
// and the code in misc/cpp/imgui_stdlib.h for how to setup InputText() for dynamically resizing strings.
// WE ARE USING A FIXED-SIZE BUFFER FOR SIMPLICITY HERE.
// If you want to use InputText() with std::string or any custom dynamic string type:
// - For std::string: use the wrapper in misc/cpp/imgui_stdlib.h/.cpp
// - Otherwise, see the 'Dear ImGui Demo->Widgets->Text Input->Resize Callback' for using ImGuiInputTextFlags_CallbackResize.
static char text[1024 * 16] =
"/*\n"
" The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
@@ -4064,7 +4072,7 @@ static void DemoWindowWidgetsTreeNodes()
{
HelpMarker(
"This is a more typical looking tree with selectable nodes.\n"
"Click to select, CTRL+Click to toggle, click on arrows or double-click to open.");
"Click to select, Ctrl+Click to toggle, click on arrows or double-click to open.");
static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth;
static bool align_label_with_current_x_position = false;
static bool test_drag_and_drop = false;
@@ -4151,7 +4159,7 @@ static void DemoWindowWidgetsTreeNodes()
// Update selection state
// (process outside of tree loop to avoid visual inconsistencies during the clicking frame)
if (ImGui::GetIO().KeyCtrl)
selection_mask ^= (1 << node_clicked); // CTRL+click to toggle
selection_mask ^= (1 << node_clicked); // Ctrl+Click to toggle
else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, may want to preserve selection when clicking on item that is part of the selection
selection_mask = (1 << node_clicked); // Click to single-select
}
@@ -5315,7 +5323,7 @@ static void DemoWindowPopups()
if (ImGui::BeginPopupContextItem()) // <-- use last item id as popup id
{
selected = n;
ImGui::Text("This a popup for \"%s\"!", names[n]);
ImGui::Text("This is a popup for \"%s\"!", names[n]);
if (ImGui::Button("Close"))
ImGui::CloseCurrentPopup();
ImGui::EndPopup();
@@ -5458,7 +5466,7 @@ static void DemoWindowPopups()
ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
ImGui::Separator();
ImGui::MenuItem("Menu item", "CTRL+M");
ImGui::MenuItem("Menu item", "Ctrl+M");
if (ImGui::BeginMenu("Menu inside a regular window"))
{
ShowExampleMenuFile();
@@ -7023,7 +7031,7 @@ static void DemoWindowTables()
// [2.3] Right-click in columns to open another custom popup
HelpMarker(
"Demonstrate mixing table context menu (over header), item context button (over button) "
"and custom per-colunm context menu (over column body).");
"and custom per-column context menu (over column body).");
ImGuiTableFlags flags2 = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders;
if (ImGui::BeginTable("table_context_menu_2", COLUMNS_COUNT, flags2))
{
@@ -7889,16 +7897,16 @@ static void DemoWindowInputs()
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 0.0f, 1.0f, 0.1f));
ImGui::BeginChild("WindowA", ImVec2(-FLT_MIN, line_height * 14), true);
ImGui::Text("Press CTRL+A and see who receives it!");
ImGui::Text("Press Ctrl+A and see who receives it!");
ImGui::Separator();
// 1: Window polling for CTRL+A
// 1: Window polling for Ctrl+A
ImGui::Text("(in WindowA)");
ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
// 2: InputText also polling for CTRL+A: it always uses _RouteFocused internally (gets priority when active)
// 2: InputText also polling for Ctrl+A: it always uses _RouteFocused internally (gets priority when active)
// (Commented because the owner-aware version of Shortcut() is still in imgui_internal.h)
//char str[16] = "Press CTRL+A";
//char str[16] = "Press Ctrl+A";
//ImGui::Spacing();
//ImGui::InputText("InputTextB", str, IM_ARRAYSIZE(str), ImGuiInputTextFlags_ReadOnly);
//ImGuiID item_id = ImGui::GetItemID();
@@ -7911,7 +7919,7 @@ static void DemoWindowInputs()
ImGui::Text("IsWindowFocused: %d", ImGui::IsWindowFocused());
ImGui::EndChild();
// 4: Child window polling for CTRL+A. It is deeper than WindowA and gets priority when focused.
// 4: Child window polling for Ctrl+A. It is deeper than WindowA and gets priority when focused.
ImGui::BeginChild("ChildE", ImVec2(-FLT_MIN, line_height * 4), true);
ImGui::Text("(in ChildE: using same Shortcut)");
ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
@@ -7968,7 +7976,7 @@ static void DemoWindowInputs()
IMGUI_DEMO_MARKER("Inputs & Focus/Tabbing");
if (ImGui::TreeNode("Tabbing"))
{
ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
ImGui::Text("Use Tab/Shift+Tab to cycle through keyboard editable fields.");
static char buf[32] = "hello";
ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
@@ -8177,6 +8185,25 @@ void ImGui::ShowAboutWindow(bool* p_open)
ImGui::Text("define: __EMSCRIPTEN__");
ImGui::Text("Emscripten: %d.%d.%d", __EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__);
#endif
#ifdef NDEBUG
ImGui::Text("define: NDEBUG");
#endif
// Heuristic to detect no-op IM_ASSERT() macros
// - This is designed so people opening bug reports would convey and notice that they have disabled asserts for Dear ImGui code.
// - 16 is > strlen("((void)(_EXPR))") which we suggested in our imconfig.h template as a possible way to disable.
int assert_runs_expression = 0;
IM_ASSERT(++assert_runs_expression);
int assert_expand_len = (int)strlen(IM_STRINGIFY((IM_ASSERT(true))));
bool assert_maybe_disabled = (!assert_runs_expression || assert_expand_len <= 16);
ImGui::Text("IM_ASSERT: runs expression: %s. expand size: %s%s",
assert_runs_expression ? "OK" : "KO", (assert_expand_len > 16) ? "OK" : "KO", assert_maybe_disabled ? " (MAYBE DISABLED?!)" : "");
if (assert_maybe_disabled)
{
ImGui::SameLine();
HelpMarker("IM_ASSERT() calls assert() by default. Compiling with NDEBUG will usually strip out assert() to nothing, which is NOT recommended because we use asserts to notify of programmer mistakes!");
}
ImGui::Separator();
ImGui::Text("io.BackendPlatformName: %s", io.BackendPlatformName ? io.BackendPlatformName : "NULL");
ImGui::Text("io.BackendRendererName: %s", io.BackendRendererName ? io.BackendRendererName : "NULL");
@@ -8512,7 +8539,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
ShowFontAtlas(atlas);
// Post-baking font scaling. Note that this is NOT the nice way of scaling fonts, read below.
// (we enforce hard clamping manually as by default DragFloat/SliderFloat allows CTRL+Click text to get out of bounds).
// (we enforce hard clamping manually as by default DragFloat/SliderFloat allows Ctrl+Click text to get out of bounds).
/*
SeparatorText("Legacy Scaling");
const float MIN_SCALE = 0.3f;
@@ -8614,27 +8641,27 @@ void ImGui::ShowUserGuide()
ImGuiIO& io = GetIO();
BulletText("Double-click on title bar to collapse window.");
BulletText(
"Click and drag on lower corner to resize window\n"
"(double-click to auto fit window to its contents).");
BulletText("CTRL+Click on a slider or drag box to input value as text.");
BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
BulletText("CTRL+Tab to select a window.");
"Click and drag on lower corner or border to resize window.\n"
"(double-click to auto fit window to its contents)");
BulletText("Ctrl+Click on a slider or drag box to input value as text.");
BulletText("Tab/Shift+Tab to cycle through keyboard editable fields.");
BulletText("Ctrl+Tab/Ctrl+Shift+Tab to focus windows.");
if (io.FontAllowUserScaling)
BulletText("CTRL+Mouse Wheel to zoom window contents.");
BulletText("Ctrl+Mouse Wheel to zoom window contents.");
BulletText("While inputting text:\n");
Indent();
BulletText("CTRL+Left/Right to word jump.");
BulletText("CTRL+A or double-click to select all.");
BulletText("CTRL+X/C/V to use clipboard cut/copy/paste.");
BulletText("CTRL+Z to undo, CTRL+Y/CTRL+SHIFT+Z to redo.");
BulletText("ESCAPE to revert.");
BulletText("Ctrl+Left/Right to word jump.");
BulletText("Ctrl+A or double-click to select all.");
BulletText("Ctrl+X/C/V to use clipboard cut/copy/paste.");
BulletText("Ctrl+Z to undo, Ctrl+Y/Ctrl+Shift+Z to redo.");
BulletText("Escape to revert.");
Unindent();
BulletText("With keyboard navigation enabled:");
Indent();
BulletText("Arrow keys to navigate.");
BulletText("Arrow keys or Home/End/PageUp/PageDown to navigate.");
BulletText("Space to activate a widget.");
BulletText("Return to input text into a widget.");
BulletText("Escape to deactivate a widget, close popup, exit child window.");
BulletText("Escape to deactivate a widget, close popup,\nexit a child window or the menu layer, clear focus.");
BulletText("Alt to jump to the menu layer of a window.");
Unindent();
}
@@ -8661,12 +8688,12 @@ static void ShowExampleAppMainMenuBar()
}
if (ImGui::BeginMenu("Edit"))
{
if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item
if (ImGui::MenuItem("Undo", "Ctrl+Z")) {}
if (ImGui::MenuItem("Redo", "Ctrl+Y", false, false)) {} // Disabled item
ImGui::Separator();
if (ImGui::MenuItem("Cut", "CTRL+X")) {}
if (ImGui::MenuItem("Copy", "CTRL+C")) {}
if (ImGui::MenuItem("Paste", "CTRL+V")) {}
if (ImGui::MenuItem("Cut", "Ctrl+X")) {}
if (ImGui::MenuItem("Copy", "Ctrl+C")) {}
if (ImGui::MenuItem("Paste", "Ctrl+V")) {}
ImGui::EndMenu();
}
ImGui::EndMainMenuBar();
@@ -9671,7 +9698,7 @@ static void ShowExampleAppConstrainedResize(bool* p_open)
}
else
{
ImGui::Text("(Hold SHIFT to display a dummy viewport)");
ImGui::Text("(Hold Shift to display a dummy viewport)");
if (ImGui::Button("Set 200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
if (ImGui::Button("Set 500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
if (ImGui::Button("Set 800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
@@ -10608,7 +10635,7 @@ struct ExampleAssetsBrowser
ImGui::SeparatorText("Layout");
ImGui::SliderFloat("Icon Size", &IconSize, 16.0f, 128.0f, "%.0f");
ImGui::SameLine(); HelpMarker("Use CTRL+Wheel to zoom");
ImGui::SameLine(); HelpMarker("Use Ctrl+Wheel to zoom");
ImGui::SliderInt("Icon Spacing", &IconSpacing, 0, 32);
ImGui::SliderInt("Icon Hit Spacing", &IconHitSpacing, 0, 32);
ImGui::Checkbox("Stretch Spacing", &StretchSpacing);
@@ -10800,7 +10827,7 @@ struct ExampleAssetsBrowser
if (want_delete)
Selection.ApplyDeletionPostLoop(ms_io, Items, item_curr_idx_to_focus);
// Zooming with CTRL+Wheel
// Zooming with Ctrl+Wheel
if (ImGui::IsWindowAppearing())
ZoomWheelAccum = 0.0f;
if (ImGui::IsWindowHovered() && io.MouseWheel != 0.0f && ImGui::IsKeyDown(ImGuiMod_Ctrl) && ImGui::IsAnyItemActive() == false)

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.92.4
// dear imgui, v1.92.5
// (drawing and font code)
/*
@@ -240,6 +240,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst)
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border];
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_DragDropTargetBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_UnsavedMarker] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
colors[ImGuiCol_NavCursor] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
@@ -306,6 +307,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst)
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border];
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_DragDropTargetBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_UnsavedMarker] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
colors[ImGuiCol_NavCursor] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
@@ -373,6 +375,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border];
colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
colors[ImGuiCol_DragDropTargetBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_UnsavedMarker] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
colors[ImGuiCol_NavCursor] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.70f, 0.70f, 0.70f, 0.70f);
@@ -824,7 +827,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
const bool use_texture = (Flags & ImDrawListFlags_AntiAliasedLinesUseTex) && (integer_thickness < IM_DRAWLIST_TEX_LINES_WIDTH_MAX) && (fractional_thickness <= 0.00001f) && (AA_SIZE == 1.0f);
// We should never hit this, because NewFrame() doesn't set ImDrawListFlags_AntiAliasedLinesUseTex unless ImFontAtlasFlags_NoBakedLines is off
IM_ASSERT_PARANOID(!use_texture || !(_Data->Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedLines));
IM_ASSERT_PARANOID(!use_texture || !(_Data->Font->OwnerAtlas->Flags & ImFontAtlasFlags_NoBakedLines));
const int idx_count = use_texture ? (count * 6) : (thick_line ? count * 18 : count * 12);
const int vtx_count = use_texture ? (points_count * 2) : (thick_line ? points_count * 4 : points_count * 3);
@@ -2653,6 +2656,7 @@ ImFontAtlas::~ImFontAtlas()
TexData = NULL;
}
// If you call this mid-frame, you would need to add new font and bind them!
void ImFontAtlas::Clear()
{
bool backup_renderer_has_textures = RendererHasTextures;
@@ -2703,6 +2707,8 @@ void ImFontAtlas::ClearFonts()
{
// FIXME-NEWATLAS: Illegal to remove currently bound font.
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
for (ImFont* font : Fonts)
ImFontAtlasBuildNotifySetFont(this, font, NULL);
ImFontAtlasBuildDestroy(this);
ClearInputData();
Fonts.clear_delete();
@@ -3197,7 +3203,7 @@ ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* compressed
// On font removal we need to remove references (otherwise we could queue removal?)
// We allow old_font == new_font which forces updating all values (e.g. sizes)
static void ImFontAtlasBuildNotifySetFont(ImFontAtlas* atlas, ImFont* old_font, ImFont* new_font)
void ImFontAtlasBuildNotifySetFont(ImFontAtlas* atlas, ImFont* old_font, ImFont* new_font)
{
for (ImDrawListSharedData* shared_data : atlas->DrawListSharedDatas)
{
@@ -3242,7 +3248,7 @@ void ImFontAtlas::RemoveFont(ImFont* font)
ImFontAtlasBuildUpdatePointers(this);
font->ContainerAtlas = NULL;
font->OwnerAtlas = NULL;
IM_DELETE(font);
// Notify external systems
@@ -3620,7 +3626,7 @@ void ImFontAtlasFontSourceAddToFont(ImFontAtlas* atlas, ImFont* font, ImFontConf
{
font->ClearOutputData();
//font->FontSize = src->SizePixels;
font->ContainerAtlas = atlas;
font->OwnerAtlas = atlas;
IM_ASSERT(font->Sources[0] == src);
}
atlas->TexIsBuilt = false; // For legacy backends
@@ -3630,6 +3636,11 @@ void ImFontAtlasFontSourceAddToFont(ImFontAtlas* atlas, ImFont* font, ImFontConf
void ImFontAtlasFontDestroySourceData(ImFontAtlas* atlas, ImFontConfig* src)
{
IM_UNUSED(atlas);
// IF YOU GET A CRASH IN THE IM_FREE() CALL HERE AND USED AddFontFromMemoryTTF():
// - DUE TO LEGACY REASON AddFontFromMemoryTTF() TRANSFERS MEMORY OWNERSHIP BY DEFAULT.
// - IT WILL THEREFORE CRASH WHEN PASSED DATA WHICH MAY NOT BE FREEED BY IMGUI.
// - USE `ImFontConfig font_cfg; font_cfg.FontDataOwnedByAtlas = false; io.Fonts->AddFontFromMemoryTTF(....., &cfg);` to disable passing ownership/
// WE WILL ADDRESS THIS IN A FUTURE REWORK OF THE API.
if (src->FontDataOwnedByAtlas)
IM_FREE(src->FontData);
src->FontData = NULL;
@@ -3643,7 +3654,7 @@ void ImFontAtlasFontDestroySourceData(ImFontAtlas* atlas, ImFontConfig* src)
// FIXME-NEWATLAS: This borrows too much from FontLoader's FontLoadGlyph() handlers and suggest that we should add further helpers.
static ImFontGlyph* ImFontAtlasBuildSetupFontBakedEllipsis(ImFontAtlas* atlas, ImFontBaked* baked)
{
ImFont* font = baked->ContainerFont;
ImFont* font = baked->OwnerFont;
IM_ASSERT(font->EllipsisChar != 0);
const ImFontGlyph* dot_glyph = baked->FindGlyphNoFallback((ImWchar)'.');
@@ -3689,7 +3700,7 @@ static void ImFontAtlasBuildSetupFontBakedFallback(ImFontBaked* baked)
{
IM_ASSERT(baked->FallbackGlyphIndex == -1);
IM_ASSERT(baked->FallbackAdvanceX == 0.0f);
ImFont* font = baked->ContainerFont;
ImFont* font = baked->OwnerFont;
ImFontGlyph* fallback_glyph = NULL;
if (font->FallbackChar != 0)
fallback_glyph = baked->FindGlyphNoFallback(font->FallbackChar);
@@ -3699,7 +3710,7 @@ static void ImFontAtlasBuildSetupFontBakedFallback(ImFontBaked* baked)
ImFontGlyph glyph;
glyph.Codepoint = 0;
glyph.AdvanceX = space_glyph ? space_glyph->AdvanceX : IM_ROUND(baked->Size * 0.40f);
fallback_glyph = ImFontAtlasBakedAddFontGlyph(font->ContainerAtlas, baked, NULL, &glyph);
fallback_glyph = ImFontAtlasBakedAddFontGlyph(font->OwnerAtlas, baked, NULL, &glyph);
}
baked->FallbackGlyphIndex = baked->Glyphs.index_from_ptr(fallback_glyph); // Storing index avoid need to update pointer on growth and simplify inner loop code
baked->FallbackAdvanceX = fallback_glyph->AdvanceX;
@@ -3780,7 +3791,7 @@ ImFontBaked* ImFontAtlasBakedAdd(ImFontAtlas* atlas, ImFont* font, float font_si
baked->Size = font_size;
baked->RasterizerDensity = font_rasterizer_density;
baked->BakedId = baked_id;
baked->ContainerFont = font;
baked->OwnerFont = font;
baked->LastUsedFrame = atlas->Builder->FrameCount;
// Initialize backend data
@@ -3815,7 +3826,7 @@ ImFontBaked* ImFontAtlasBakedGetClosestMatch(ImFontAtlas* atlas, ImFont* font, f
for (int baked_n = 0; baked_n < builder->BakedPool.Size; baked_n++)
{
ImFontBaked* baked = &builder->BakedPool[baked_n];
if (baked->ContainerFont != font || baked->WantDestroy)
if (baked->OwnerFont != font || baked->WantDestroy)
continue;
if (step_n == 0 && baked->RasterizerDensity != font_rasterizer_density) // First try with same density
continue;
@@ -3871,7 +3882,7 @@ void ImFontAtlasFontDiscardBakes(ImFontAtlas* atlas, ImFont* font, int unused_fr
ImFontBaked* baked = &builder->BakedPool[baked_n];
if (baked->LastUsedFrame + unused_frames > atlas->Builder->FrameCount)
continue;
if (baked->ContainerFont != font || baked->WantDestroy)
if (baked->OwnerFont != font || baked->WantDestroy)
continue;
ImFontAtlasBakedDiscard(atlas, font, baked);
}
@@ -3886,9 +3897,9 @@ void ImFontAtlasBuildDiscardBakes(ImFontAtlas* atlas, int unused_frames)
ImFontBaked* baked = &builder->BakedPool[baked_n];
if (baked->LastUsedFrame + unused_frames > atlas->Builder->FrameCount)
continue;
if (baked->WantDestroy || (baked->ContainerFont->Flags & ImFontFlags_LockBakedSizes))
if (baked->WantDestroy || (baked->OwnerFont->Flags & ImFontFlags_LockBakedSizes))
continue;
ImFontAtlasBakedDiscard(atlas, baked->ContainerFont, baked);
ImFontAtlasBakedDiscard(atlas, baked->OwnerFont, baked);
}
}
@@ -3909,6 +3920,11 @@ void ImFontAtlasRemoveDrawListSharedData(ImFontAtlas* atlas, ImDrawListSharedDat
void ImFontAtlasUpdateDrawListsTextures(ImFontAtlas* atlas, ImTextureRef old_tex, ImTextureRef new_tex)
{
for (ImDrawListSharedData* shared_data : atlas->DrawListSharedDatas)
{
// If Context 2 uses font owned by Context 1 which already called EndFrame()/Render(), we don't want to mess with draw commands for Context 1
if (shared_data->Context && !shared_data->Context->WithinFrameScope)
continue;
for (ImDrawList* draw_list : shared_data->DrawLists)
{
// Replace in command-buffer
@@ -3922,6 +3938,7 @@ void ImFontAtlasUpdateDrawListsTextures(ImFontAtlas* atlas, ImTextureRef old_tex
if (stacked_tex == old_tex)
stacked_tex = new_tex;
}
}
}
// Update texture coordinates in all draw list shared context
@@ -4421,8 +4438,8 @@ static void ImFontAtlas_FontHookRemapCodepoint(ImFontAtlas* atlas, ImFont* font,
static ImFontGlyph* ImFontBaked_BuildLoadGlyph(ImFontBaked* baked, ImWchar codepoint, float* only_load_advance_x)
{
ImFont* font = baked->ContainerFont;
ImFontAtlas* atlas = font->ContainerAtlas;
ImFont* font = baked->OwnerFont;
ImFontAtlas* atlas = font->OwnerAtlas;
if (atlas->Locked || (font->Flags & ImFontFlags_NoLoadGlyphs))
{
// Lazily load fallback glyph
@@ -4696,7 +4713,7 @@ static bool ImGui_ImplStbTrueType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontC
stbtt_MakeGlyphBitmapSubpixelPrefilter(&bd_font_data->FontInfo, bitmap_pixels, w, h, w,
scale_for_raster_x, scale_for_raster_y, 0, 0, oversample_h, oversample_v, &sub_x, &sub_y, glyph_index);
const float ref_size = baked->ContainerFont->Sources[0]->SizePixels;
const float ref_size = baked->OwnerFont->Sources[0]->SizePixels;
const float offsets_scale = (ref_size != 0.0f) ? (baked->Size / ref_size) : 1.0f;
float font_off_x = (src->GlyphOffset.x * offsets_scale);
float font_off_y = (src->GlyphOffset.y * offsets_scale);
@@ -5023,7 +5040,9 @@ const ImWchar* ImFontAtlas::GetGlyphRangesVietnamese()
void ImFontGlyphRangesBuilder::AddText(const char* text, const char* text_end)
{
while (text_end ? (text < text_end) : *text)
if (text_end == NULL)
text_end = text + strlen(text);
while (text < text_end)
{
unsigned int c = 0;
int c_len = ImTextCharFromUtf8(&c, text, text_end);
@@ -5091,7 +5110,7 @@ ImFont::~ImFont()
void ImFont::ClearOutputData()
{
if (ImFontAtlas* atlas = ContainerAtlas)
if (ImFontAtlas* atlas = OwnerAtlas)
ImFontAtlasFontDiscardBakes(atlas, this, 0);
FallbackChar = EllipsisChar = 0;
memset(Used8kPagesMap, 0, sizeof(Used8kPagesMap));
@@ -5136,7 +5155,7 @@ ImFontGlyph* ImFontAtlasBakedAddFontGlyph(ImFontAtlas* atlas, ImFontBaked* baked
if (src != NULL)
{
// Clamp & recenter if needed
const float ref_size = baked->ContainerFont->Sources[0]->SizePixels;
const float ref_size = baked->OwnerFont->Sources[0]->SizePixels;
const float offsets_scale = (ref_size != 0.0f) ? (baked->Size / ref_size) : 1.0f;
float advance_x = ImClamp(glyph->AdvanceX, src->GlyphMinAdvanceX * offsets_scale, src->GlyphMaxAdvanceX * offsets_scale);
if (advance_x != glyph->AdvanceX)
@@ -5162,7 +5181,7 @@ ImFontGlyph* ImFontAtlasBakedAddFontGlyph(ImFontAtlas* atlas, ImFontBaked* baked
baked->IndexAdvanceX[codepoint] = glyph->AdvanceX;
baked->IndexLookup[codepoint] = (ImU16)glyph_idx;
const int page_n = codepoint / 8192;
baked->ContainerFont->Used8kPagesMap[page_n >> 3] |= 1 << (page_n & 7);
baked->OwnerFont->Used8kPagesMap[page_n >> 3] |= 1 << (page_n & 7);
return glyph;
}
@@ -5174,7 +5193,7 @@ void ImFontAtlasBakedAddFontGlyphAdvancedX(ImFontAtlas* atlas, ImFontBaked* bake
if (src != NULL)
{
// Clamp & recenter if needed
const float ref_size = baked->ContainerFont->Sources[0]->SizePixels;
const float ref_size = baked->OwnerFont->Sources[0]->SizePixels;
const float offsets_scale = (ref_size != 0.0f) ? (baked->Size / ref_size) : 1.0f;
advance_x = ImClamp(advance_x, src->GlyphMinAdvanceX * offsets_scale, src->GlyphMaxAdvanceX * offsets_scale);
@@ -5196,7 +5215,7 @@ void ImFontAtlasBakedSetFontGlyphBitmap(ImFontAtlas* atlas, ImFontBaked* baked,
ImTextureData* tex = atlas->TexData;
IM_ASSERT(r->x + r->w <= tex->Width && r->y + r->h <= tex->Height);
ImFontAtlasTextureBlockConvert(src_pixels, src_fmt, src_pitch, (unsigned char*)tex->GetPixelsAt(r->x, r->y), tex->Format, tex->GetPitch(), r->w, r->h);
ImFontAtlasPostProcessData pp_data = { atlas, baked->ContainerFont, src, baked, glyph, tex->GetPixelsAt(r->x, r->y), tex->Format, tex->GetPitch(), r->w, r->h };
ImFontAtlasPostProcessData pp_data = { atlas, baked->OwnerFont, src, baked, glyph, tex->GetPixelsAt(r->x, r->y), tex->Format, tex->GetPitch(), r->w, r->h };
ImFontAtlasTextureBlockPostProcess(&pp_data);
ImFontAtlasTextureBlockQueueUpload(atlas, tex, r->x, r->y, r->w, r->h);
}
@@ -5254,7 +5273,7 @@ bool ImFontBaked::IsGlyphLoaded(ImWchar c)
// This is not fast query
bool ImFont::IsGlyphInFont(ImWchar c)
{
ImFontAtlas* atlas = ContainerAtlas;
ImFontAtlas* atlas = OwnerAtlas;
ImFontAtlas_FontHookRemapCodepoint(atlas, this, &c);
for (ImFontConfig* src : Sources)
{
@@ -5303,7 +5322,7 @@ ImFontBaked* ImFont::GetFontBaked(float size, float density)
if (baked && baked->Size == size && baked->RasterizerDensity == density)
return baked;
ImFontAtlas* atlas = ContainerAtlas;
ImFontAtlas* atlas = OwnerAtlas;
ImFontAtlasBuilder* builder = atlas->Builder;
baked = ImFontAtlasBakedGetOrAdd(atlas, this, size, density);
if (baked == NULL)
@@ -5324,7 +5343,7 @@ ImFontBaked* ImFontAtlasBakedGetOrAdd(ImFontAtlas* atlas, ImFont* font, float fo
ImFontBaked* baked = *p_baked_in_map;
if (baked != NULL)
{
IM_ASSERT(baked->Size == font_size && baked->ContainerFont == font && baked->BakedId == baked_id);
IM_ASSERT(baked->Size == font_size && baked->OwnerFont == font && baked->BakedId == baked_id);
return baked;
}

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.92.4
// dear imgui, v1.92.5
// (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.
@@ -209,6 +209,7 @@ typedef int ImGuiSeparatorFlags; // -> enum ImGuiSeparatorFlags_ // F
typedef int ImGuiTextFlags; // -> enum ImGuiTextFlags_ // Flags: for TextEx()
typedef int ImGuiTooltipFlags; // -> enum ImGuiTooltipFlags_ // Flags: for BeginTooltipEx()
typedef int ImGuiTypingSelectFlags; // -> enum ImGuiTypingSelectFlags_ // Flags: for GetTypingSelectRequest()
typedef int ImGuiWindowBgClickFlags; // -> enum ImGuiWindowBgClickFlags_ // Flags: for overriding behavior of clicking on window background/void.
typedef int ImGuiWindowRefreshFlags; // -> enum ImGuiWindowRefreshFlags_ // Flags: for SetNextWindowRefreshPolicy()
// Table column indexing
@@ -277,10 +278,8 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
#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)) // ImTrunc() is not inlined in MSVC debug builds
#define IM_ROUND(_VAL) ((float)(int)((_VAL) + 0.5f)) //
#define IM_STRINGIFY_HELPER(_X) #_X
#define IM_STRINGIFY(_X) IM_STRINGIFY_HELPER(_X) // Preprocessor idiom to stringify e.g. an integer.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
#define IM_FLOOR IM_TRUNC
#define IM_FLOOR IM_TRUNC // [OBSOLETE] Renamed in 1.90.0 (Sept 2023)
#endif
// Hint for branch prediction
@@ -427,7 +426,8 @@ IMGUI_API int ImTextStrFromUtf8(ImWchar* out_buf, int out_buf_size, co
IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count)
IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end); // return number of bytes to express one char in UTF-8
IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8
IMGUI_API const char* ImTextFindPreviousUtf8Codepoint(const char* in_text_start, const char* in_text_curr); // return previous UTF-8 code-point.
IMGUI_API const char* ImTextFindPreviousUtf8Codepoint(const char* in_text_start, const char* in_p); // return previous UTF-8 code-point.
IMGUI_API const char* ImTextFindValidUtf8CodepointEnd(const char* in_text_start, const char* in_text_end, const char* in_p); // return previous UTF-8 code-point if 'in_p' is not the end of a valid one.
IMGUI_API int ImTextCountLines(const char* in_text, const char* in_text_end); // return number of lines taken by text. trailing carriage return doesn't count as an extra line.
// Helpers: High-level text functions (DO NOT USE!!! THIS IS A MINIMAL SUBSET OF LARGER UPCOMING CHANGES)
@@ -1173,6 +1173,7 @@ struct IMGUI_API ImGuiGroupData
ImVec2 BackupCurrLineSize;
float BackupCurrLineTextBaseOffset;
ImGuiID BackupActiveIdIsAlive;
bool BackupActiveIdHasBeenEditedThisFrame;
bool BackupDeactivatedIdIsAlive;
bool BackupHoveredIdIsAlive;
bool BackupIsSameLine;
@@ -1282,6 +1283,12 @@ enum ImGuiWindowRefreshFlags_
// Refresh policy/frequency, Load Balancing etc.
};
enum ImGuiWindowBgClickFlags_
{
ImGuiWindowBgClickFlags_None = 0,
ImGuiWindowBgClickFlags_Move = 1 << 0, // Click on bg/void + drag to move window. Cleared by default when using io.ConfigWindowsMoveFromTitleBarOnly.
};
enum ImGuiNextWindowDataFlags_
{
ImGuiNextWindowDataFlags_None = 0,
@@ -1715,7 +1722,7 @@ enum ImGuiNavMoveFlags_
ImGuiNavMoveFlags_WrapMask_ = ImGuiNavMoveFlags_LoopX | ImGuiNavMoveFlags_LoopY | ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_WrapY,
ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place)
ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, // Store alternate result in NavMoveResultLocalVisible that only comprise elements that are already fully visible (used by PageUp/PageDown)
ImGuiNavMoveFlags_ScrollToEdgeY = 1 << 6, // Force scrolling to min/max (used by Home/End) // FIXME-NAV: Aim to remove or reword, probably unnecessary
ImGuiNavMoveFlags_ScrollToEdgeY = 1 << 6, // Force scrolling to min/max (used by Home/End) // FIXME-NAV: Aim to remove or reword as ImGuiScrollFlags
ImGuiNavMoveFlags_Forwarded = 1 << 7,
ImGuiNavMoveFlags_DebugNoResult = 1 << 8, // Dummy scoring for debug purpose, don't apply result
ImGuiNavMoveFlags_FocusApi = 1 << 9, // Requests from focus API can land/focus/activate items even if they are marked with _NoTabStop (see NavProcessItemForTabbingRequest() for details)
@@ -2113,27 +2120,34 @@ struct ImGuiMetricsConfig
struct ImGuiStackLevelInfo
{
ImGuiID ID;
ImS8 QueryFrameCount; // >= 1: Query in progress
bool QuerySuccess; // Obtained result from DebugHookIdInfo()
ImS8 QueryFrameCount; // >= 1: Sub-query in progress
bool QuerySuccess; // Sub-query obtained result from DebugHookIdInfo()
ImS8 DataType; // ImGuiDataType
int DescOffset; // -1 or offset into parent's ResultPathsBuf
int DescOffset; // -1 or offset into parent's ResultsPathsBuf
ImGuiStackLevelInfo() { memset(this, 0, sizeof(*this)); DescOffset = -1; }
ImGuiStackLevelInfo() { memset(this, 0, sizeof(*this)); DataType = -1; DescOffset = -1; }
};
struct ImGuiDebugItemPathQuery
{
ImGuiID MainID; // ID to query details for.
bool Active; // Used to disambiguate the case when ID == 0 and e.g. some code calls PushOverrideID(0).
bool Complete; // All sub-queries are finished (some may have failed).
ImS8 Step; // -1: query stack + init Results, >= 0: filling individual stack level.
ImVector<ImGuiStackLevelInfo> Results;
ImGuiTextBuffer ResultsDescBuf;
ImGuiTextBuffer ResultPathBuf;
ImGuiDebugItemPathQuery() { memset(this, 0, sizeof(*this)); }
};
// State for ID Stack tool queries
struct ImGuiIDStackTool
{
int LastActiveFrame;
int StackLevel; // -1: query stack and resize Results, >= 0: individual stack level
ImGuiID QueryMainId; // ID to query details for
ImVector<ImGuiStackLevelInfo> Results;
bool QueryHookActive; // Used to disambiguate the case where DebugHookIdInfoId == 0 which is valid.
bool OptHexEncodeNonAsciiChars;
bool OptCopyToClipboardOnCtrlC;
int LastActiveFrame;
float CopyToClipboardLastTime;
ImGuiTextBuffer ResultPathsBuf;
ImGuiTextBuffer ResultTempBuf;
ImGuiIDStackTool() { memset(this, 0, sizeof(*this)); LastActiveFrame = -1; OptHexEncodeNonAsciiChars = true; CopyToClipboardLastTime = -FLT_MAX; }
};
@@ -2163,6 +2177,14 @@ struct ImGuiContextHook
struct ImGuiContext
{
bool Initialized;
bool WithinFrameScope; // Set by NewFrame(), cleared by EndFrame()
bool WithinFrameScopeWithImplicitWindow; // Set by NewFrame(), cleared by EndFrame() when the implicit debug window has been pushed
bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log()
int FrameCount;
int FrameCountEnded;
int FrameCountRendered;
double Time;
char ContextName[16]; // Storage for a context name (to facilitate debugging multi-context setups)
ImGuiIO IO;
ImGuiPlatformIO PlatformIO;
ImGuiStyle Style;
@@ -2175,17 +2197,8 @@ struct ImGuiContext
float FontRasterizerDensity; // Current font density. Used by all calls to GetFontBaked().
float CurrentDpiScale; // Current window/viewport DpiScale == CurrentViewport->DpiScale
ImDrawListSharedData DrawListSharedData;
double Time;
int FrameCount;
int FrameCountEnded;
int FrameCountRendered;
ImGuiID WithinEndChildID; // Set within EndChild()
bool WithinFrameScope; // Set by NewFrame(), cleared by EndFrame()
bool WithinFrameScopeWithImplicitWindow; // Set by NewFrame(), cleared by EndFrame() when the implicit debug window has been pushed
bool GcCompactAll; // Request full GC
bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log()
void* TestEngine; // Test engine user data
char ContextName[16]; // Storage for a context name (to facilitate debugging multi-context setups)
// Inputs
ImVector<ImGuiInputEvent> InputEventsQueue; // Input events which will be trickled/written into IO structure.
@@ -2236,11 +2249,11 @@ struct ImGuiContext
bool ActiveIdHasBeenEditedBefore; // Was the value associated to the widget Edited over the course of the Active state.
bool ActiveIdHasBeenEditedThisFrame;
bool ActiveIdFromShortcut;
ImS8 ActiveIdMouseButton;
ImGuiID ActiveIdDisabledId; // When clicking a disabled item we set ActiveId=window->MoveId to avoid interference with widget code. Actual item ID is stored here.
int ActiveIdMouseButton : 8;
ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior)
ImGuiWindow* ActiveIdWindow;
ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad
ImGuiWindow* ActiveIdWindow;
ImGuiID ActiveIdPreviousFrame;
ImGuiDeactivatedItemData DeactivatedItemData;
ImGuiDataTypeStorage ActiveIdValueOnActivation; // Backup of initial value at the time of activation. ONLY SET BY SPECIFIC WIDGETS: DragXXX and SliderXXX.
@@ -2270,6 +2283,7 @@ struct ImGuiContext
ImGuiLastItemData LastItemData; // Storage for last submitted item (setup by ItemAdd)
ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions
bool DebugShowGroupRects;
bool GcCompactAll; // Request full GC
// Shared stacks
ImGuiCol DebugFlashStyleColorIdx; // (Keep close to ColorStack to share cache line)
@@ -2343,13 +2357,13 @@ struct ImGuiContext
bool NavJustMovedToIsTabbing; // 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: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
bool ConfigNavWindowingWithGamepad; // = true. Enable CTRL+TAB by holding ImGuiKey_GamepadFaceLeft (== ImGuiKey_NavGamepadMenu). When false, the button may still be used to toggle Menu layer.
// Navigation: Windowing (Ctrl+Tab for list, or Menu button + keys or directional pads to move/resize)
bool ConfigNavWindowingWithGamepad; // = true. Enable Ctrl+Tab by holding ImGuiKey_GamepadFaceLeft (== ImGuiKey_NavGamepadMenu). When false, the button may still be used to toggle Menu layer.
ImGuiKeyChord ConfigNavWindowingKeyNext; // = ImGuiMod_Ctrl | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiKey_Tab on OS X). For reconfiguration (see #4828)
ImGuiKeyChord ConfigNavWindowingKeyPrev; // = ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiMod_Shift | ImGuiKey_Tab on OS X)
ImGuiWindow* NavWindowingTarget; // Target window when doing CTRL+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most!
ImGuiWindow* NavWindowingTarget; // Target window when doing Ctrl+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most!
ImGuiWindow* NavWindowingTargetAnim; // Record of last valid NavWindowingTarget until DimBgRatio and NavWindowingHighlightAlpha becomes 0.0f, so the fade-out can stay on it.
ImGuiWindow* NavWindowingListWindow; // Internal window actually listing the CTRL+Tab contents
ImGuiWindow* NavWindowingListWindow; // Internal window actually listing the Ctrl+Tab contents
float NavWindowingTimer;
float NavWindowingHighlightAlpha;
ImGuiInputSource NavWindowingInputSource;
@@ -2359,7 +2373,7 @@ struct ImGuiContext
ImVec2 NavWindowingAccumDeltaSize;
// Render
float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list)
float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and Ctrl+Tab list)
// Drag and Drop
bool DragDropActive;
@@ -2373,7 +2387,8 @@ struct ImGuiContext
ImRect DragDropTargetClipRect; // Store ClipRect at the time of item's drawing
ImGuiID DragDropTargetId;
ImGuiID DragDropTargetFullViewport;
ImGuiDragDropFlags DragDropAcceptFlags;
ImGuiDragDropFlags DragDropAcceptFlagsCurr;
ImGuiDragDropFlags DragDropAcceptFlagsPrev;
float DragDropAcceptIdCurrRectSurface; // Target item surface (we resolve overlapping targets by prioritizing the smaller surface)
ImGuiID DragDropAcceptIdCurr; // Target item id (set at the time of accepting the payload)
ImGuiID DragDropAcceptIdPrev; // Target item id from previous frame (we need to store this to allow for overlapping drag and drop targets)
@@ -2427,7 +2442,7 @@ struct ImGuiContext
ImGuiInputTextDeactivatedState InputTextDeactivatedState;
ImFontBaked InputTextPasswordFontBackupBaked;
ImFontFlags InputTextPasswordFontBackupFlags;
ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc.
ImGuiID TempInputId; // Temporary text input when using Ctrl+Click on a slider, etc.
ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types
int BeginMenuDepth;
int BeginComboDepth;
@@ -2480,6 +2495,7 @@ struct ImGuiContext
// Capture/Logging
bool LogEnabled; // Currently capturing
bool LogLineFirstItem;
ImGuiLogFlags LogFlags; // Capture flags/type
ImGuiWindow* LogWindow;
ImFileHandle LogFile; // If != NULL log to stdout/ file
@@ -2487,7 +2503,6 @@ struct ImGuiContext
const char* LogNextPrefix; // See comment in LogSetNextTextDecoration(): doesn't copy underlying data, use carefully!
const char* LogNextSuffix;
float LogLinePosY;
bool LogLineFirstItem;
int LogDepthRef;
int LogDepthToExpand;
int LogDepthToExpandDefault; // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call.
@@ -2503,7 +2518,7 @@ struct ImGuiContext
// Debug Tools
// (some of the highly frequently used data are interleaved in other structures above: DebugBreakXXX fields, DebugHookIdInfo, DebugLocateId etc.)
int DebugDrawIdConflictsCount; // Locked count (preserved when holding CTRL)
int DebugDrawIdConflictsCount; // Locked count (preserved when holding Ctrl)
ImGuiDebugLogFlags DebugLogFlags;
ImGuiTextBuffer DebugLogBuf;
ImGuiTextIndex DebugLogIndex;
@@ -2520,6 +2535,7 @@ struct ImGuiContext
float DebugFlashStyleColorTime;
ImVec4 DebugFlashStyleColorBackup;
ImGuiMetricsConfig DebugMetricsConfig;
ImGuiDebugItemPathQuery DebugItemPathQuery;
ImGuiIDStackTool DebugIDStackTool;
ImGuiDebugAllocInfo DebugAllocInfo;
#if defined(IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS) && !defined(IMGUI_DISABLE_DEBUG_TOOLS)
@@ -2539,6 +2555,7 @@ struct ImGuiContext
char TempKeychordName[64];
ImGuiContext(ImFontAtlas* shared_font_atlas);
~ImGuiContext();
};
//-----------------------------------------------------------------------------
@@ -2654,13 +2671,14 @@ struct IMGUI_API ImGuiWindow
short BeginOrderWithinParent; // Begin() order within immediate parent window, if we are a child window. Otherwise 0.
short BeginOrderWithinContext; // Begin() order within entire imgui context. This is mostly used for debugging submission order related issues.
short FocusOrder; // Order within WindowsFocusOrder[], altered when windows are focused.
ImGuiDir AutoPosLastDirection;
ImS8 AutoFitFramesX, AutoFitFramesY;
bool AutoFitOnlyGrows;
ImGuiDir AutoPosLastDirection;
ImS8 HiddenFramesCanSkipItems; // Hide the window for N frames
ImS8 HiddenFramesCannotSkipItems; // Hide the window for N frames while allowing items to be submitted so we can measure their size
ImS8 HiddenFramesForRenderOnly; // Hide the window until frame N at Render() time only
ImS8 DisableInputsFrames; // Disable window interactions for N frames
ImGuiWindowBgClickFlags BgClickFlags : 8; // Configure behavior of click+dragging on window bg/void or over items. Default sets by io.ConfigWindowsMoveFromTitleBarOnly. If you use this please report in #3379.
ImGuiCond SetWindowPosAllowFlags : 8; // store acceptable condition flags for SetNextWindowPos() use.
ImGuiCond SetWindowSizeAllowFlags : 8; // store acceptable condition flags for SetNextWindowSize() use.
ImGuiCond SetWindowCollapsedAllowFlags : 8; // store acceptable condition flags for SetNextWindowCollapsed() use.
@@ -2700,7 +2718,7 @@ struct IMGUI_API ImGuiWindow
ImGuiWindow* RootWindowPopupTree; // Point to ourself or first ancestor that is not a child window. Cross through popups parent<>child.
ImGuiWindow* RootWindowForTitleBarHighlight; // Point to ourself or first ancestor which will display TitleBgActive color when this window is active.
ImGuiWindow* RootWindowForNav; // Point to ourself or first ancestor which doesn't have the NavFlattened flag.
ImGuiWindow* ParentWindowForFocusRoute; // Set to manual link a window to its logical parent so that Shortcut() chain are honoerd (e.g. Tool linked to Document)
ImGuiWindow* ParentWindowForFocusRoute; // Set to manual link a window to its logical parent so that Shortcut() chain are honored (e.g. Tool linked to Document)
ImGuiWindow* NavLastChildNavWindow; // When going to the menu bar, we remember the child window we came from. (This could probably be made implicit if we kept g.Windows sorted by last focused including child window.)
ImGuiID NavLastIds[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1)
@@ -2727,7 +2745,7 @@ public:
ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight)); }
ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight; return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight); }
// [Obsolete] ImGuiWindow::CalcFontSize() was removed in 1.92.x because error-prone/misleading. You can use window->FontRefSize for a copy of g.FontSize at the time of the last Begin() call for this window.
// [OBSOLETE] ImGuiWindow::CalcFontSize() was removed in 1.92.0 because error-prone/misleading. You can use window->FontRefSize for a copy of g.FontSize at the time of the last Begin() call for this window.
//float CalcFontSize() const { ImGuiContext& g = *Ctx; return g.FontSizeBase * FontWindowScale * FontWindowScaleParents;
};
@@ -2781,7 +2799,7 @@ struct IMGUI_API ImGuiTabBar
ImGuiID ID; // Zero for tab-bars used by docking
ImGuiID SelectedTabId; // Selected tab/window
ImGuiID NextSelectedTabId; // Next selected tab/window. Will also trigger a scrolling animation
ImGuiID VisibleTabId; // Can occasionally be != SelectedTabId (e.g. when previewing contents for CTRL+TAB preview)
ImGuiID VisibleTabId; // Can occasionally be != SelectedTabId (e.g. when previewing contents for Ctrl+Tab preview)
int CurrFrameVisible;
int PrevFrameVisible;
ImRect BarRect;
@@ -3021,7 +3039,7 @@ struct IMGUI_API ImGuiTable
bool IsContextPopupOpen; // Set when default context menu is open (also see: ContextPopupColumn, InstanceInteracted).
bool DisableDefaultContextMenu; // Disable default context menu. You may submit your own using TableBeginContextMenuPopup()/EndPopup()
bool IsSettingsRequestLoad;
bool IsSettingsDirty; // Set when table settings have changed and needs to be reported into ImGuiTableSetttings data.
bool IsSettingsDirty; // Set when table settings have changed and needs to be reported into ImGuiTableSettings data.
bool IsDefaultDisplayOrder; // Set when display order is unchanged from default (DisplayOrder contains 0...Count-1)
bool IsResetAllRequest;
bool IsResetDisplayOrderRequest;
@@ -3045,6 +3063,7 @@ struct IMGUI_API ImGuiTable
// sizeof() ~ 136 bytes.
struct IMGUI_API ImGuiTableTempData
{
ImGuiID WindowID; // Shortcut to g.Tables[TableIndex]->OuterWindow->ID.
int TableIndex; // Index in g.Tables.Buf[] pool
float LastTimeActive; // Last timestamp this structure was used
float AngledHeadersExtraWidth; // Used in EndTable()
@@ -3125,6 +3144,7 @@ namespace ImGui
IMGUI_API void UpdateWindowSkipRefresh(ImGuiWindow* window);
IMGUI_API ImVec2 CalcWindowNextAutoFitSize(ImGuiWindow* window);
IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent, bool popup_hierarchy);
IMGUI_API bool IsWindowInBeginStack(ImGuiWindow* window);
IMGUI_API bool IsWindowWithinBeginStackOf(ImGuiWindow* window, ImGuiWindow* potential_parent);
IMGUI_API bool IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below);
IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window);
@@ -3380,7 +3400,7 @@ namespace ImGui
// Legacy functions use ImGuiKeyOwner_Any meaning that they typically ignore ownership, unless a call to SetKeyOwner() explicitly used ImGuiInputFlags_LockThisFrame or ImGuiInputFlags_LockUntilRelease.
// - Binding generators may want to ignore those for now, or suffix them with Ex() until we decide if this gets moved into public API.
IMGUI_API bool IsKeyDown(ImGuiKey key, ImGuiID owner_id);
IMGUI_API bool IsKeyPressed(ImGuiKey key, ImGuiInputFlags flags, ImGuiID owner_id = 0); // Important: when transitioning from old to new IsKeyPressed(): old API has "bool repeat = true", so would default to repeat. New API requiress explicit ImGuiInputFlags_Repeat.
IMGUI_API bool IsKeyPressed(ImGuiKey key, ImGuiInputFlags flags, ImGuiID owner_id = 0); // Important: when transitioning from old to new IsKeyPressed(): old API has "bool repeat = true", so would default to repeat. New API requires explicit ImGuiInputFlags_Repeat.
IMGUI_API bool IsKeyReleased(ImGuiKey key, ImGuiID owner_id);
IMGUI_API bool IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id = 0);
IMGUI_API bool IsMouseDown(ImGuiMouseButton button, ImGuiID owner_id);
@@ -3844,6 +3864,7 @@ IMGUI_API void ImFontAtlasBuildInit(ImFontAtlas* atlas);
IMGUI_API void ImFontAtlasBuildDestroy(ImFontAtlas* atlas);
IMGUI_API void ImFontAtlasBuildMain(ImFontAtlas* atlas);
IMGUI_API void ImFontAtlasBuildSetupFontLoader(ImFontAtlas* atlas, const ImFontLoader* font_loader);
IMGUI_API void ImFontAtlasBuildNotifySetFont(ImFontAtlas* atlas, ImFont* old_font, ImFont* new_font);
IMGUI_API void ImFontAtlasBuildUpdatePointers(ImFontAtlas* atlas);
IMGUI_API void ImFontAtlasBuildRenderBitmapFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char);
IMGUI_API void ImFontAtlasBuildClear(ImFontAtlas* atlas); // Clear output and custom rects

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.92.4
// dear imgui, v1.92.5
// (tables and columns code)
/*
@@ -24,9 +24,9 @@ Index of this file:
*/
// Navigating this file:
// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// - 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.
// - In Visual Studio: Ctrl+Comma ("Edit.GoToAll") can follow symbols inside comments, whereas Ctrl+F12 ("Edit.GoToImplementation") cannot.
// - 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.
//-----------------------------------------------------------------------------
// [SECTION] Commentary
@@ -451,7 +451,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
// But at this point we do NOT have a correct value for .Max.y (unless a height has been explicitly passed in). It will only be updated in EndTable().
table->WorkRect = table->OuterRect = table->InnerRect = outer_rect;
table->HasScrollbarYPrev = table->HasScrollbarYCurr = false;
table->InnerWindow->DC.TreeDepth++; // This is designed to always linking ImGuiTreeNodeFlags_DrawLines linking accross a table
table->InnerWindow->DC.TreeDepth++; // This is designed to always linking ImGuiTreeNodeFlags_DrawLines linking across a table
}
// Push a standardized ID for both child-using and not-child-using tables
@@ -464,6 +464,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->HostIndentX = inner_window->DC.Indent.x;
table->HostClipRect = inner_window->ClipRect;
table->HostSkipItems = inner_window->SkipItems;
temp_data->WindowID = inner_window->ID;
temp_data->HostBackupWorkRect = inner_window->WorkRect;
temp_data->HostBackupParentWorkRect = inner_window->ParentWorkRect;
temp_data->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset;
@@ -946,7 +947,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// (e.g. TextWrapped) too much. Otherwise what tends to happen is that TextWrapped would output a very
// large height (= first frame scrollbar display very off + clipper would skip lots of items).
// This is merely making the side-effect less extreme, but doesn't properly fixes it.
// FIXME: Move this to ->WidthGiven to avoid temporary lossyless?
// FIXME: Move this to ->WidthGiven to avoid temporary lossyness?
// FIXME: This break IsPreserveWidthAuto from not flickering if the stored WidthAuto was smaller.
if (column->AutoFitQueue > 0x01 && table->IsInitializing && !column->IsPreserveWidthAuto)
column->WidthRequest = ImMax(column->WidthRequest, table->MinColumnWidth * 4.0f); // FIXME-TABLE: Another constant/scale?
@@ -1190,7 +1191,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
}
// In case the table is visible (e.g. decorations) but all columns clipped, we keep a column visible.
// Else if give no chance to a clipper-savy user to submit rows and therefore total contents height used by scrollbar.
// Else if give no chance to a clipper-savvy user to submit rows and therefore total contents height used by scrollbar.
if (has_at_least_one_column_requesting_output == false)
{
table->Columns[table->LeftMostEnabledColumn].IsRequestOutput = true;
@@ -1366,7 +1367,7 @@ void ImGui::EndTable()
ImGuiWindow* inner_window = table->InnerWindow;
ImGuiWindow* outer_window = table->OuterWindow;
ImGuiTableTempData* temp_data = table->TempData;
IM_ASSERT(inner_window == g.CurrentWindow);
IM_ASSERT(inner_window == g.CurrentWindow && inner_window->ID == temp_data->WindowID);
IM_ASSERT(outer_window == inner_window || outer_window == inner_window->ParentWindow);
if (table->IsInsideRow)
@@ -1559,7 +1560,7 @@ void ImGui::EndTable()
IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table);
IM_ASSERT(g.TablesTempDataStacked > 0);
temp_data = (--g.TablesTempDataStacked > 0) ? &g.TablesTempData[g.TablesTempDataStacked - 1] : NULL;
g.CurrentTable = temp_data ? g.Tables.GetByIndex(temp_data->TableIndex) : NULL;
g.CurrentTable = temp_data && (temp_data->WindowID == outer_window->ID) ? g.Tables.GetByIndex(temp_data->TableIndex) : NULL;
if (g.CurrentTable)
{
g.CurrentTable->TempData = temp_data;
@@ -2525,7 +2526,7 @@ void ImGui::TablePopColumnChannel()
// - NoClip --> 2+D+1 channels: bg0/1 + bg2 + foreground (same clip rect == always 1 draw call)
// - Clip --> 2+D+N channels
// - FreezeRows --> 2+D+N*2 (unless scrolling value is zero)
// - FreezeRows || FreezeColunns --> 3+D+N*2 (unless scrolling value is zero)
// - FreezeRows || FreezeColumns --> 3+D+N*2 (unless scrolling value is zero)
// Where D is 1 if any column is clipped or hidden (dummy channel) otherwise 0.
void ImGui::TableSetupDrawChannels(ImGuiTable* table)
{
@@ -3420,7 +3421,7 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label
// Left<>Right alignment
float line_off_curr_x = flip_label ? (label_lines - 1) * line_off_step_x : 0.0f;
float line_off_for_align_x = ImMax((((column->MaxX - column->MinX) - padding.x * 2.0f) - (label_lines * line_off_step_x)), 0.0f) * align.x;
float line_off_for_align_x = ImFloor(ImMax((((column->MaxX - column->MinX) - padding.x * 2.0f) - (label_lines * line_off_step_x)), 0.0f) * align.x);
line_off_curr_x += line_off_for_align_x - line_off_for_ascent_x;
// Register header width
@@ -4027,9 +4028,9 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
bool open = TreeNode(table, "Table 0x%08X (%d columns, in '%s')%s", table->ID, table->ColumnsCount, table->OuterWindow->Name, is_active ? "" : " *Inactive*");
if (!is_active) { PopStyleColor(); }
if (IsItemHovered())
GetForegroundDrawList()->AddRect(table->OuterRect.Min, table->OuterRect.Max, IM_COL32(255, 255, 0, 255));
GetForegroundDrawList(table->OuterWindow)->AddRect(table->OuterRect.Min, table->OuterRect.Max, IM_COL32(255, 255, 0, 255));
if (IsItemVisible() && table->HoveredColumnBody != -1)
GetForegroundDrawList()->AddRect(GetItemRectMin(), GetItemRectMax(), IM_COL32(255, 255, 0, 255));
GetForegroundDrawList(table->OuterWindow)->AddRect(GetItemRectMin(), GetItemRectMax(), IM_COL32(255, 255, 0, 255));
if (!open)
return;
if (table->InstanceCurrent > 0)
@@ -4083,7 +4084,7 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
if (IsItemHovered())
{
ImRect r(column->MinX, table->OuterRect.Min.y, column->MaxX, table->OuterRect.Max.y);
GetForegroundDrawList()->AddRect(r.Min, r.Max, IM_COL32(255, 255, 0, 255));
GetForegroundDrawList(table->OuterWindow)->AddRect(r.Min, r.Max, IM_COL32(255, 255, 0, 255));
}
}
if (ImGuiTableSettings* settings = TableGetBoundSettings(table))

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.92.4
// dear imgui, v1.92.5
// (widgets code)
/*
@@ -574,8 +574,9 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
// Special mode for Drag and Drop used by openables (tree nodes, tabs etc.)
// where holding the button pressed for a long time while drag a payload item triggers the button.
if (g.DragDropActive && (flags & ImGuiButtonFlags_PressedOnDragDropHold) && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoHoldToOpenOthers))
if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
if (g.DragDropActive)
{
if ((flags & ImGuiButtonFlags_PressedOnDragDropHold) && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoHoldToOpenOthers) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
{
hovered = true;
SetHoveredID(id);
@@ -586,6 +587,9 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
FocusWindow(window);
}
}
if (g.DragDropAcceptIdPrev == id && (g.DragDropAcceptFlagsPrev & ImGuiDragDropFlags_AcceptDrawAsHovered))
hovered = true;
}
if (flatten_hovered_children)
g.HoveredWindow = backup_hovered_window;
@@ -619,7 +623,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
if (flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere))
{
SetActiveID(id, window);
g.ActiveIdMouseButton = mouse_button_clicked;
g.ActiveIdMouseButton = (ImS8)mouse_button_clicked;
if (!(flags & ImGuiButtonFlags_NoNavFocus))
{
SetFocusID(id, window);
@@ -637,7 +641,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
ClearActiveID();
else
SetActiveID(id, window); // Hold on ID
g.ActiveIdMouseButton = mouse_button_clicked;
g.ActiveIdMouseButton = (ImS8)mouse_button_clicked;
if (!(flags & ImGuiButtonFlags_NoNavFocus))
{
SetFocusID(id, window);
@@ -675,32 +679,35 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
// Keyboard/Gamepad navigation handling
// We report navigated and navigation-activated items as hovered but we don't set g.HoveredId to not interfere with mouse.
if (g.NavId == id && g.NavCursorVisible && g.NavHighlightItemUnderNav)
if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus))
hovered = true;
if (g.NavActivateDownId == id)
if ((item_flags & ImGuiItemFlags_Disabled) == 0)
{
bool nav_activated_by_code = (g.NavActivateId == id);
bool nav_activated_by_inputs = (g.NavActivatePressedId == id);
if (!nav_activated_by_inputs && (item_flags & ImGuiItemFlags_ButtonRepeat))
if (g.NavId == id && g.NavCursorVisible && g.NavHighlightItemUnderNav)
if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus))
hovered = true;
if (g.NavActivateDownId == id)
{
// Avoid pressing multiple keys from triggering excessive amount of repeat events
const ImGuiKeyData* key1 = GetKeyData(ImGuiKey_Space);
const ImGuiKeyData* key2 = GetKeyData(ImGuiKey_Enter);
const ImGuiKeyData* key3 = GetKeyData(ImGuiKey_NavGamepadActivate);
const float t1 = ImMax(ImMax(key1->DownDuration, key2->DownDuration), key3->DownDuration);
nav_activated_by_inputs = CalcTypematicRepeatAmount(t1 - g.IO.DeltaTime, t1, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0;
}
if (nav_activated_by_code || nav_activated_by_inputs)
{
// Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button.
pressed = true;
SetActiveID(id, window);
g.ActiveIdSource = g.NavInputSource;
if (!(flags & ImGuiButtonFlags_NoNavFocus) && !(g.NavActivateFlags & ImGuiActivateFlags_FromShortcut))
SetFocusID(id, window);
if (g.NavActivateFlags & ImGuiActivateFlags_FromShortcut)
g.ActiveIdFromShortcut = true;
bool nav_activated_by_code = (g.NavActivateId == id);
bool nav_activated_by_inputs = (g.NavActivatePressedId == id);
if (!nav_activated_by_inputs && (item_flags & ImGuiItemFlags_ButtonRepeat))
{
// Avoid pressing multiple keys from triggering excessive amount of repeat events
const ImGuiKeyData* key1 = GetKeyData(ImGuiKey_Space);
const ImGuiKeyData* key2 = GetKeyData(ImGuiKey_Enter);
const ImGuiKeyData* key3 = GetKeyData(ImGuiKey_NavGamepadActivate);
const float t1 = ImMax(ImMax(key1->DownDuration, key2->DownDuration), key3->DownDuration);
nav_activated_by_inputs = CalcTypematicRepeatAmount(t1 - g.IO.DeltaTime, t1, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0;
}
if (nav_activated_by_code || nav_activated_by_inputs)
{
// Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button.
pressed = true;
SetActiveID(id, window);
g.ActiveIdSource = g.NavInputSource;
if (!(flags & ImGuiButtonFlags_NoNavFocus) && !(g.NavActivateFlags & ImGuiActivateFlags_FromShortcut))
SetFocusID(id, window);
if (g.NavActivateFlags & ImGuiActivateFlags_FromShortcut)
g.ActiveIdFromShortcut = true;
}
}
}
@@ -754,7 +761,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
}
// Activation highlight (this may be a remote activation)
if (g.NavHighlightActivatedId == id)
if (g.NavHighlightActivatedId == id && (item_flags & ImGuiItemFlags_Disabled) == 0)
hovered = true;
if (out_hovered) *out_hovered = hovered;
@@ -2694,7 +2701,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id);
if (!temp_input_is_active)
{
// Tabbing or CTRL+click on Drag turns it into an InputText
// Tabbing or Ctrl+Click on Drag turns it into an InputText
const bool clicked = hovered && IsMouseClicked(0, ImGuiInputFlags_None, id);
const bool double_clicked = (hovered && g.IO.MouseClickedCount[0] == 2 && TestKeyOwner(ImGuiKey_MouseLeft, id));
const bool make_active = (clicked || double_clicked || g.NavActivateId == id);
@@ -2728,7 +2735,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
if (temp_input_is_active)
{
// Only clamp CTRL+Click input when ImGuiSliderFlags_ClampOnInput is set (generally via ImGuiSliderFlags_AlwaysClamp)
// Only clamp Ctrl+Click input when ImGuiSliderFlags_ClampOnInput is set (generally via ImGuiSliderFlags_AlwaysClamp)
bool clamp_enabled = false;
if ((flags & ImGuiSliderFlags_ClampOnInput) && (p_min != NULL || p_max != NULL))
{
@@ -3298,7 +3305,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id);
if (!temp_input_is_active)
{
// Tabbing or CTRL+click on Slider turns it into an input box
// Tabbing or Ctrl+Click on Slider turns it into an input box
const bool clicked = hovered && IsMouseClicked(0, ImGuiInputFlags_None, id);
const bool make_active = (clicked || g.NavActivateId == id);
if (make_active && clicked)
@@ -3322,7 +3329,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
if (temp_input_is_active)
{
// Only clamp CTRL+Click input when ImGuiSliderFlags_ClampOnInput is set (generally via ImGuiSliderFlags_AlwaysClamp)
// Only clamp Ctrl+Click input when ImGuiSliderFlags_ClampOnInput is set (generally via ImGuiSliderFlags_AlwaysClamp)
const bool clamp_enabled = (flags & ImGuiSliderFlags_ClampOnInput) != 0;
return TempInputScalar(frame_bb, id, label, data_type, p_data, format, clamp_enabled ? p_min : NULL, clamp_enabled ? p_max : NULL);
}
@@ -3659,7 +3666,7 @@ int ImParseFormatPrecision(const char* fmt, int default_precision)
return (precision == INT_MAX) ? default_precision : precision;
}
// Create text input in place of another active widget (e.g. used when doing a CTRL+Click on drag/slider widgets)
// Create text input in place of another active widget (e.g. used when doing a Ctrl+Click on drag/slider widgets)
// FIXME: Facilitate using this in variety of other situations.
// FIXME: Among other things, setting ImGuiItemFlags_AllowDuplicateId in LastItemData is currently correct but
// the expected relationship between TempInputXXX functions and LastItemData is a little fishy.
@@ -3685,7 +3692,7 @@ bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char*
}
// Note that Drag/Slider functions are only forwarding the min/max values clamping values if the ImGuiSliderFlags_AlwaysClamp flag is set!
// This is intended: this way we allow CTRL+Click manual input to set a value out of bounds, for maximum flexibility.
// This is intended: this way we allow Ctrl+Click manual input to set a value out of bounds, for maximum flexibility.
// However this may not be ideal for all uses, as some user code may break on out of bound values.
bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min, const void* p_clamp_max)
{
@@ -3920,6 +3927,7 @@ namespace ImStb
#include "imstb_textedit.h"
}
// If you want to use InputText() with std::string or any custom dynamic string type, use the wrapper in misc/cpp/imgui_stdlib.h/.cpp!
bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
{
IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline()
@@ -4004,7 +4012,7 @@ static bool ImCharIsSeparatorW(unsigned int c)
static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx)
{
// When ImGuiInputTextFlags_Password is set, we don't want actions such as CTRL+Arrow to leak the fact that underlying data are blanks or separators.
// When ImGuiInputTextFlags_Password is set, we don't want actions such as Ctrl+Arrow to leak the fact that underlying data are blanks or separators.
if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0)
return 0;
@@ -4142,21 +4150,23 @@ static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
obj->TextLen -= n;
}
static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const char* new_text, int new_text_len)
static int STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const char* new_text, int new_text_len)
{
const bool is_resizable = (obj->Flags & ImGuiInputTextFlags_CallbackResize) != 0;
const int text_len = obj->TextLen;
IM_ASSERT(pos <= text_len);
if (!is_resizable && (new_text_len + obj->TextLen + 1 > obj->BufCapacity))
return false;
// We support partial insertion (with a mod in stb_textedit.h)
const int avail = obj->BufCapacity - 1 - obj->TextLen;
if (!is_resizable && new_text_len > avail)
new_text_len = (int)(ImTextFindValidUtf8CodepointEnd(new_text, new_text + new_text_len, new_text + avail) - new_text); // Truncate to closest UTF-8 codepoint. Alternative: return 0 to cancel insertion.
if (new_text_len == 0)
return 0;
// Grow internal buffer if needed
IM_ASSERT(obj->TextSrc == obj->TextA.Data);
if (new_text_len + text_len + 1 > obj->TextA.Size)
if (text_len + new_text_len + 1 > obj->TextA.Size && is_resizable)
{
if (!is_resizable)
return false;
obj->TextA.resize(text_len + ImClamp(new_text_len, 32, ImMax(256, new_text_len)) + 1);
obj->TextSrc = obj->TextA.Data;
}
@@ -4170,7 +4180,7 @@ static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const ch
obj->TextLen += new_text_len;
obj->TextA[obj->TextLen] = '\0';
return true;
return new_text_len;
}
// We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols)
@@ -4205,7 +4215,8 @@ static void stb_textedit_replace(ImGuiInputTextState* str, STB_TexteditState* st
state->cursor = state->select_start = state->select_end = 0;
if (text_len <= 0)
return;
if (ImStb::STB_TEXTEDIT_INSERTCHARS(str, 0, text, text_len))
int text_len_inserted = ImStb::STB_TEXTEDIT_INSERTCHARS(str, 0, text, text_len);
if (text_len_inserted > 0)
{
state->cursor = state->select_start = state->select_end = text_len;
state->has_preferred_x = 0;
@@ -4300,15 +4311,20 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
ImGuiContext& g = *Ctx;
ImGuiInputTextState* obj = &g.InputTextState;
IM_ASSERT(obj->ID != 0 && g.ActiveId == obj->ID);
const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0;
const bool is_readonly = (Flags & ImGuiInputTextFlags_ReadOnly) != 0;
int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)ImStrlen(new_text);
// We support partial insertion (with a mod in stb_textedit.h)
const int avail = BufSize - 1 - BufTextLen;
if (!is_resizable && new_text_len > avail)
new_text_len = (int)(ImTextFindValidUtf8CodepointEnd(new_text, new_text + new_text_len, new_text + avail) - new_text); // Truncate to closest UTF-8 codepoint. Alternative: return 0 to cancel insertion.
if (new_text_len == 0)
return;
// Grow internal buffer if needed
const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0;
const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)ImStrlen(new_text);
if (new_text_len + BufTextLen + 1 > obj->TextA.Size && (Flags & ImGuiInputTextFlags_ReadOnly) == 0)
if (new_text_len + BufTextLen + 1 > obj->TextA.Size && is_resizable && !is_readonly)
{
if (!is_resizable)
return;
IM_ASSERT(Buf == obj->TextA.Data);
int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1;
obj->TextA.resize(new_buf_size + 1);
@@ -4612,9 +4628,7 @@ static ImVec2 InputTextLineIndexGetPosOffset(ImGuiContext& g, ImGuiInputTextStat
// This is so we can easily call InputText() on static arrays using ARRAYSIZE() and to match
// Note that in std::string world, capacity() would omit 1 byte used by the zero-terminator.
// - When active, hold on a privately held copy of the text (and apply back to 'buf'). So changing 'buf' while the InputText is active has no effect.
// - If you want to use ImGui::InputText() with std::string, see misc/cpp/imgui_stdlib.h
// (FIXME: Rather confusing and messy function, among the worse part of our codebase, expecting to rewrite a V2 at some point.. Partly because we are
// doing UTF8 > U16 > UTF8 conversions on the go to easily interface with stb_textedit. Ideally should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188)
// - If you want to use InputText() with std::string or any custom dynamic string type, use the wrapper in misc/cpp/imgui_stdlib.h/.cpp!
bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* callback_user_data)
{
ImGuiWindow* window = GetCurrentWindow();
@@ -4748,8 +4762,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
state->TextLen = new_len;
memcpy(state->TextA.Data, buf, state->TextLen + 1);
state->Stb->select_start = state->ReloadSelectionStart;
state->Stb->cursor = state->Stb->select_end = state->ReloadSelectionEnd;
state->CursorClamp();
state->Stb->cursor = state->Stb->select_end = state->ReloadSelectionEnd; // will be clamped to bounds below
}
else if ((init_state && g.ActiveId != id) || init_changed_specs)
{
@@ -4789,9 +4802,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Recycle existing cursor/selection/undo stack but clamp position
// Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler.
if (recycle_state)
state->CursorClamp();
else
if (!recycle_state)
stb_textedit_initialize_state(state->Stb, !is_multiline);
if (!is_multiline)
@@ -4820,7 +4831,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{
// Declare some inputs, the other are registered and polled via Shortcut() routing system.
// FIXME: The reason we don't use Shortcut() is we would need a routing flag to specify multiple mods, or to all mods combination into individual shortcuts.
const ImGuiKey always_owned_keys[] = { ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_Enter, ImGuiKey_KeypadEnter, ImGuiKey_Delete, ImGuiKey_Backspace, ImGuiKey_Home, ImGuiKey_End };
const ImGuiKey always_owned_keys[] = { ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_Delete, ImGuiKey_Backspace, ImGuiKey_Home, ImGuiKey_End };
for (ImGuiKey key : always_owned_keys)
SetKeyOwner(key, id);
if (user_clicked)
@@ -4848,6 +4859,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Read-only mode always ever read from source buffer. Refresh TextLen when active.
if (is_readonly && state != NULL)
state->TextLen = (int)ImStrlen(buf);
if (state != NULL)
state->CursorClamp();
//if (is_readonly && state != NULL)
// state->TextA.clear(); // Uncomment to facilitate debugging, but we otherwise prefer to keep/amortize th allocation.
}
@@ -4914,7 +4927,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if ((multiclick_count % 2) == 0)
{
// Double-click: Select word
// We always use the "Mac" word advance for double-click select vs CTRL+Right which use the platform dependent variant:
// We always use the "Mac" word advance for double-click select vs Ctrl+Right which use the platform dependent variant:
// FIXME: There are likely many ways to improve this behavior, but there's no "right" behavior (depends on use-case, software, OS)
const bool is_bol = (state->Stb->cursor == 0) || ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb->cursor - 1) == '\n';
if (STB_TEXT_HAS_SELECTION(state->Stb) || !is_bol)
@@ -4983,7 +4996,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
}
// Process regular text input (before we check for Return because using some IME will effectively send a Return?)
// We ignore CTRL inputs, but need to allow ALT+CTRL as some keyboards (e.g. German) use AltGR (which _is_ Alt+Ctrl) to input certain characters.
// We ignore Ctrl inputs, but need to allow Alt+Ctrl as some keyboards (e.g. German) use AltGR (which _is_ Alt+Ctrl) to input certain characters.
const bool ignore_char_inputs = (io.KeyCtrl && !io.KeyAlt) || (is_osx && io.KeyCtrl);
if (io.InputQueueCharacters.Size > 0)
{
@@ -5016,7 +5029,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl
const bool is_startend_key_down = is_osx && io.KeyCtrl && !io.KeySuper && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End
// Using Shortcut() with ImGuiInputFlags_RouteFocused (default policy) to allow routing operations for other code (e.g. calling window trying to use CTRL+A and CTRL+B: former would be handled by InputText)
// Using Shortcut() with ImGuiInputFlags_RouteFocused (default policy) to allow routing operations for other code (e.g. calling window trying to use Ctrl+A and Ctrl+B: former would be handled by InputText)
// Otherwise we could simply assume that we own the keys as we are active.
const ImGuiInputFlags f_repeat = ImGuiInputFlags_Repeat;
const bool is_cut = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_X, f_repeat, id) || Shortcut(ImGuiMod_Shift | ImGuiKey_Delete, f_repeat, id)) && !is_readonly && !is_password && (!is_multiline || state->HasSelection());
@@ -5028,7 +5041,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful.
const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
const bool is_enter_pressed = IsKeyPressed(ImGuiKey_Enter, true) || IsKeyPressed(ImGuiKey_KeypadEnter, true);
const bool is_enter = Shortcut(ImGuiKey_Enter, f_repeat, id) || Shortcut(ImGuiKey_KeypadEnter, f_repeat, id);
const bool is_ctrl_enter = Shortcut(ImGuiMod_Ctrl | ImGuiKey_Enter, f_repeat, id) || Shortcut(ImGuiMod_Ctrl | ImGuiKey_KeypadEnter, f_repeat, id);
const bool is_gamepad_validate = nav_gamepad_active && (IsKeyPressed(ImGuiKey_NavGamepadActivate, false) || IsKeyPressed(ImGuiKey_NavGamepadInput, false));
const bool is_cancel = Shortcut(ImGuiKey_Escape, f_repeat, id) || (nav_gamepad_active && Shortcut(ImGuiKey_NavGamepadCancel, f_repeat, id));
@@ -5063,11 +5077,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
}
state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask);
}
else if (is_enter_pressed || is_gamepad_validate)
else if (is_enter || is_ctrl_enter || is_gamepad_validate)
{
// Determine if we turn Enter into a \n character
bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0;
if (!is_multiline || is_gamepad_validate || (ctrl_enter_for_new_line != io.KeyCtrl))
if (!is_multiline || is_gamepad_validate || (ctrl_enter_for_new_line != is_ctrl_enter))
{
validated = true;
if (io.ConfigInputTextEnterKeepActive && !is_multiline)
@@ -5077,7 +5091,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
}
else if (!is_readonly)
{
unsigned int c = '\n'; // Insert new line
// Insert new line
unsigned int c = '\n';
if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data))
state->OnCharPressed(c);
}
@@ -5139,12 +5154,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{
// Filter pasted buffer
const int clipboard_len = (int)ImStrlen(clipboard);
const char* clipboard_end = clipboard + clipboard_len;
ImVector<char> clipboard_filtered;
clipboard_filtered.reserve(clipboard_len + 1);
for (const char* s = clipboard; *s != 0; )
{
unsigned int c;
int in_len = ImTextCharFromUtf8(&c, s, NULL);
int in_len = ImTextCharFromUtf8(&c, s, clipboard_end);
s += in_len;
if (!InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, true))
continue;
@@ -5191,7 +5207,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
apply_new_text_length = state->TextToRevertTo.Size - 1;
// Restore initial value. Only return true if restoring to the initial value changes the current buffer contents.
// Push records into the undo stack so we can CTRL+Z the revert operation itself
// Push records into the undo stack so we can Ctrl+Z the revert operation itself
value_changed = true;
stb_textedit_replace(state, state->Stb, state->TextToRevertTo.Data, state->TextToRevertTo.Size - 1);
}
@@ -5260,10 +5276,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
callback_data.BufTextLen = state->TextLen;
callback_data.BufSize = state->BufCapacity;
callback_data.BufDirty = false;
const int utf8_cursor_pos = callback_data.CursorPos = state->Stb->cursor;
const int utf8_selection_start = callback_data.SelectionStart = state->Stb->select_start;
const int utf8_selection_end = callback_data.SelectionEnd = state->Stb->select_end;
callback_data.CursorPos = state->Stb->cursor;
callback_data.SelectionStart = state->Stb->select_start;
callback_data.SelectionEnd = state->Stb->select_end;
// Call user code
callback(&callback_data);
@@ -5273,11 +5288,12 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
IM_ASSERT(callback_data.Buf == callback_buf); // Invalid to modify those fields
IM_ASSERT(callback_data.BufSize == state->BufCapacity);
IM_ASSERT(callback_data.Flags == flags);
const bool buf_dirty = callback_data.BufDirty;
if (callback_data.CursorPos != utf8_cursor_pos || buf_dirty) { state->Stb->cursor = callback_data.CursorPos; state->CursorFollow = true; }
if (callback_data.SelectionStart != utf8_selection_start || buf_dirty) { state->Stb->select_start = (callback_data.SelectionStart == callback_data.CursorPos) ? state->Stb->cursor : callback_data.SelectionStart; }
if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty) { state->Stb->select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb->select_start : callback_data.SelectionEnd; }
if (buf_dirty)
if (callback_data.BufDirty || callback_data.CursorPos != state->Stb->cursor)
state->CursorFollow = true;
state->Stb->cursor = ImClamp(callback_data.CursorPos, 0, callback_data.BufTextLen);
state->Stb->select_start = ImClamp(callback_data.SelectionStart, 0, callback_data.BufTextLen);
state->Stb->select_end = ImClamp(callback_data.SelectionEnd, 0, callback_data.BufTextLen);
if (callback_data.BufDirty)
{
// Callback may update buffer and thus set buf_dirty even in read-only mode.
IM_ASSERT(callback_data.BufTextLen == (int)ImStrlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
@@ -5401,7 +5417,12 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
line_index->Offsets.resize(0);
int line_count = 1;
if (is_multiline)
line_count = InputTextLineIndexBuild(flags, line_index, buf_display, buf_display_end, wrap_width, (render_cursor && state && state->CursorFollow) ? INT_MAX : line_visible_n1 + 1, buf_display_end ? NULL : &buf_display_end);
{
// If scrolling is expected to change build full index.
// FIXME-OPT: Could append to index when new value of line_visible_n1 becomes bigger, see second call to CalcClipRectVisibleItemsY() below.
bool will_scroll_y = state && ((state->CursorFollow && render_cursor) || (state->CursorCenterY && (render_cursor || render_selection)));
line_count = InputTextLineIndexBuild(flags, line_index, buf_display, buf_display_end, wrap_width, will_scroll_y ? INT_MAX : line_visible_n1 + 1, buf_display_end ? NULL : &buf_display_end);
}
line_index->EndOffset = (int)(buf_display_end - buf_display);
line_visible_n1 = ImMin(line_visible_n1, line_count);
@@ -5686,7 +5707,7 @@ static void ColorEditRestoreHS(const float* col, float* H, float* S, float* V)
// Edit colors components (each component in 0.0f..1.0f range).
// See enum ImGuiColorEditFlags_ for available options. e.g. Only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
// With typical options: Left-click on color square to open color picker. Right-click to open option menu. CTRL+Click over input fields to edit them and TAB to go to next item.
// With typical options: Left-click on color square to open color picker. Right-click to open option menu. Ctrl+Click over input fields to edit them and TAB to go to next item.
bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags)
{
ImGuiWindow* window = GetCurrentWindow();
@@ -7926,7 +7947,7 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel
}
}
// Shortcut: Select all (CTRL+A)
// Shortcut: Select all (Ctrl+A)
if (!(flags & ImGuiMultiSelectFlags_SingleSelect) && !(flags & ImGuiMultiSelectFlags_NoSelectAll))
if (Shortcut(ImGuiMod_Ctrl | ImGuiKey_A))
request_select_all = true;
@@ -8071,7 +8092,7 @@ void ImGui::MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags
if (ms->LoopRequestSetAll != -1)
selected = (ms->LoopRequestSetAll == 1);
// When using SHIFT+Nav: because it can incur scrolling we cannot afford a frame of lag with the selection highlight (otherwise scrolling would happen before selection)
// When using Shift+Nav: because it can incur scrolling we cannot afford a frame of lag with the selection highlight (otherwise scrolling would happen before selection)
// For this to work, we need someone to set 'RangeSrcPassedBy = true' at some point (either clipper either SetNextItemSelectionUserData() function)
if (ms->IsKeyboardSetRange)
{
@@ -8102,7 +8123,7 @@ void ImGui::MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags
// Alter button behavior flags
// To handle drag and drop of multiple items we need to avoid clearing selection on click.
// Enabling this test makes actions using CTRL+SHIFT delay their effect on MouseUp which is annoying, but it allows drag and drop of multiple items.
// Enabling this test makes actions using Ctrl+Shift delay their effect on MouseUp which is annoying, but it allows drag and drop of multiple items.
if (p_button_flags != NULL)
{
ImGuiButtonFlags button_flags = *p_button_flags;
@@ -8206,8 +8227,8 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
}
// Right-click handling.
// FIXME-MULTISELECT: Currently filtered out by ImGuiMultiSelectFlags_NoAutoSelect but maybe should be moved to Selectable(). See https://github.com/ocornut/imgui/pull/5816
if (hovered && IsMouseClicked(1) && (flags & ImGuiMultiSelectFlags_NoAutoSelect) == 0)
// FIXME-MULTISELECT: Maybe should be moved to Selectable()? Also see #5816, #8200, #9015
if (hovered && IsMouseClicked(1) && (flags & (ImGuiMultiSelectFlags_NoAutoSelect | ImGuiMultiSelectFlags_NoSelectOnRightClick)) == 0)
{
if (g.ActiveId != 0 && g.ActiveId != id)
ClearActiveID();
@@ -8301,7 +8322,7 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
MultiSelectAddSetRange(ms, range_selected, range_direction, storage->RangeSrcItem, item_data);
}
// Update/store the selection state of the Source item (used by CTRL+SHIFT, when Source is unselected we perform a range unselect)
// Update/store the selection state of the Source item (used by Ctrl+Shift, when Source is unselected we perform a range unselect)
if (storage->RangeSrcItem == item_data)
storage->RangeSelected = selected ? 1 : 0;
@@ -8515,7 +8536,7 @@ void ImGuiSelectionBasicStorage::ApplyRequests(ImGuiMultiSelectIO* ms_io)
else
{
// Append insertion + single sort likely be faster.
// Use req.RangeDirection to set order field so that shift+clicking from 1 to 5 is different than shift+clicking from 5 to 1
// Use req.RangeDirection to set order field so that Shift+Clicking from 1 to 5 is different than Shift+Clicking from 5 to 1
const int size_before_amends = _Storage.Data.Size;
int selection_order = _SelectionOrder + ((req.RangeDirection < 0) ? selection_changes - 1 : 0);
for (int idx = (int)req.RangeFirstItem; idx <= (int)req.RangeLastItem; idx++, selection_order += req.RangeDirection)
@@ -10442,7 +10463,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
}
// Lock visibility
// (Note: tab_contents_visible != tab_selected... because CTRL+TAB operations may preview some tabs without selecting them!)
// (Note: tab_contents_visible != tab_selected... because Ctrl+Tab operations may preview some tabs without selecting them!)
bool tab_contents_visible = (tab_bar->VisibleTabId == id);
if (tab_contents_visible)
tab_bar->VisibleTabWasSubmitted = true;

View File

@@ -5,7 +5,8 @@
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783)
// - Added name to struct or it may be forward declared in our code.
// - Added UTF-8 support (see https://github.com/nothings/stb/issues/188 + https://github.com/ocornut/imgui/pull/7925)
// Grep for [DEAR IMGUI] to find the changes.
// - Changed STB_TEXTEDIT_INSERTCHARS() to return inserted count (instead of 0/1 bool), allowing partial insertion.
// Grep for [DEAR IMGUI] to find some changes.
// - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_*
// stb_textedit.h - v1.14 - public domain - Sean Barrett
@@ -39,6 +40,7 @@
//
// VERSION HISTORY
//
// !!!! (2025-10-23) changed STB_TEXTEDIT_INSERTCHARS() to return inserted count (instead of 0/1 bool), allowing partial insertion.
// 1.14 (2021-07-11) page up/down, various fixes
// 1.13 (2019-02-07) fix bug in undo size management
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
@@ -147,7 +149,8 @@
// as manually wordwrapping for end-of-line positioning
//
// STB_TEXTEDIT_DELETECHARS(obj,i,n) delete n characters starting at i
// STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*)
// STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) try to insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*)
// returns number of characters actually inserted. [DEAR IMGUI]
//
// STB_TEXTEDIT_K_SHIFT a power of two that is or'd in to a keyboard input to represent the shift key
//
@@ -775,7 +778,8 @@ static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditS
stb_textedit_clamp(str, state);
stb_textedit_delete_selection(str,state);
// try to insert the characters
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) {
len = STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len);
if (len) {
stb_text_makeundo_insert(state, state->cursor, len);
state->cursor += len;
state->has_preferred_x = 0;
@@ -800,13 +804,15 @@ static void stb_textedit_text(IMSTB_TEXTEDIT_STRING* str, STB_TexteditState* sta
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
text_len = STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len);
if (text_len) {
state->cursor += text_len;
state->has_preferred_x = 0;
}
} else {
stb_textedit_delete_selection(str, state); // implicitly clamps
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
text_len = STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len);
if (text_len) {
stb_text_makeundo_insert(state, state->cursor, text_len);
state->cursor += text_len;
state->has_preferred_x = 0;
@@ -1352,7 +1358,7 @@ static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
// check type of recorded action:
if (u.insert_length) {
// easy case: was a deletion, so we need to insert n characters
STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length);
u.insert_length = STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length);
s->undo_char_point -= u.insert_length;
}
@@ -1403,7 +1409,7 @@ static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
if (r.insert_length) {
// easy case: need to insert n characters
STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length);
r.insert_length = STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length);
s->redo_char_point += r.insert_length;
}

View File

@@ -9,5 +9,9 @@ imgui_scoped.h
Try by merging: https://github.com/ocornut/imgui/pull/2197
Discuss at: https://github.com/ocornut/imgui/issues/2096
See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki:
imgui-module:
C++20 module binding
https://github.com/stripe2933/imgui-module
See more C++ related extension (fmt, RAII, syntactic sugar) on Wiki:
https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness

View File

@@ -1,10 +1,22 @@
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
// This is also an example of how you may wrap your own similar types.
// TL;DR; this is using the ImGuiInputTextFlags_CallbackResize facility,
// which also demonstrated in 'Dear ImGui Demo->Widgets->Text Input->Resize Callback'.
// Changelog:
// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
// See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki:
// Usage:
// {
// #include "misc/cpp/imgui_stdlib.h"
// #include "misc/cpp/imgui_stdlib.cpp" // <-- If you want to include implementation without messing with your project/build.
// [...]
// std::string my_string;
// ImGui::InputText("my string", &my_string);
// }
// See more C++ related extension (fmt, RAII, syntactic sugar) on Wiki:
// https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness
#include "imgui.h"

View File

@@ -1,9 +1,21 @@
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
// This is also an example of how you may wrap your own similar types.
// TL;DR; this is using the ImGuiInputTextFlags_CallbackResize facility,
// which also demonstrated in 'Dear ImGui Demo->Widgets->Text Input->Resize Callback'.
// Changelog:
// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
// Usage:
// {
// #include "misc/cpp/imgui_stdlib.h"
// #include "misc/cpp/imgui_stdlib.cpp" // <-- If you want to include implementation without messing with your project/build.
// [...]
// std::string my_string;
// ImGui::InputText("my string", &my_string);
// }
// See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki:
// https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness

View File

@@ -423,7 +423,7 @@ static bool ImGui_ImplFreeType_FontBakedInit(ImFontAtlas* atlas, ImFontConfig* s
IM_UNUSED(atlas);
float size = baked->Size;
if (src->MergeMode && src->SizePixels != 0.0f)
size *= (src->SizePixels / baked->ContainerFont->Sources[0]->SizePixels);
size *= (src->SizePixels / baked->OwnerFont->Sources[0]->SizePixels);
ImGui_ImplFreeType_FontSrcData* bd_font_data = (ImGui_ImplFreeType_FontSrcData*)src->FontLoaderData;
bd_font_data->BakedLastActivated = baked;
@@ -539,7 +539,7 @@ static bool ImGui_ImplFreeType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontConf
uint32_t* temp_buffer = (uint32_t*)atlas->Builder->TempBuffer.Data;
ImGui_ImplFreeType_BlitGlyph(ft_bitmap, temp_buffer, w);
const float ref_size = baked->ContainerFont->Sources[0]->SizePixels;
const float ref_size = baked->OwnerFont->Sources[0]->SizePixels;
const float offsets_scale = (ref_size != 0.0f) ? (baked->Size / ref_size) : 1.0f;
float font_off_x = (src->GlyphOffset.x * offsets_scale);
float font_off_y = (src->GlyphOffset.y * offsets_scale) + baked->Ascent;