Compare commits

...

415 Commits

Author SHA1 Message Date
ocornut
6d948ab47e Merge branch 'master' into docking
# Conflicts:
#	imgui.cpp
2024-06-06 17:52:55 +02:00
ocornut
6f7b5d0ee2 Version 1.90.8 2024-06-06 17:45:40 +02:00
ocornut
67d886fd63 Removed ImGuiButtonFlags_MouseButtonDefault_. 2024-06-06 17:25:16 +02:00
ocornut
2a418f054d InputText: reordered all flags. (ABI breaking) 2024-06-06 17:23:56 +02:00
ocornut
f1eaf8d7c0 Internals: added SetNextItemRefVal(). (#7305) 2024-06-06 17:01:02 +02:00
ocornut
47db0698d2 InputScalar, InputInt, InputFloat: added ImGuiInputTextFlags_ParseEmptyRefVal, ImGuiInputTextFlags_DisplayEmptyRefVal. (#7305) 2024-06-06 16:51:15 +02:00
ocornut
3460014e05 Internals: avoid using bitfields in ImGuiNextItemData as it leads to extraneous packing. rename ImGuiDataTypeTempStorage to ImGuiDataTypeStorage. moved DataType section above Widgets. 2024-06-06 16:50:32 +02:00
ocornut
0561d708ba Modals, Popups: fixed an issue preventing to close a popup opened over a modal by clicking over void. (#7654) 2024-06-05 15:55:01 +02:00
Kenneth Rapp
219c6adc58 Examples: SDL3+SDLRenderer3: Update SDL_SetRenderDrawColorFloat() call. (#7658) 2024-06-05 14:50:24 +02:00
jungnitz
b95b2b4574 Fixed (harmless) incorrect order of arguments in IsKeyChordPressed (#7657) 2024-06-05 14:45:36 +02:00
korenkonder
209edcc247 Fixed incorrect order of arguments in IsMouseClicked(). (#7657, #456)
Amend 85513de24
2024-06-04 17:29:59 +02:00
ocornut
fdc084f532 Merge branch 'master' into docking 2024-06-03 19:08:37 +02:00
ocornut
a31aa683ff Tables: fixed an issue where ideal size reported to parent container wouldn't correctly take account of inner scrollbar. (#7651) 2024-06-03 19:02:28 +02:00
ocornut
f8de9fec8c Backends: SDL3: Update for SDL_SYSTEM_CURSOR_xxx api renames. (#7653) 2024-06-03 18:25:58 +02:00
ocornut
68a05e3f04 Tables: fixed a bug where after disabling the ScrollY flag for a table, previous scrollbar width would be accounted for. (#5920)
Amend 317b33d6
2024-06-03 17:17:13 +02:00
ocornut
6cefd4fd88 Scrollbar: fixed miscalculation of vertical scrollbar visibility when required solely by the presence of an horizontal scrollbar. (#1574)
Initially fixed by 2d9d7a10c, and broken back by a0994d74c2 (v1.71, wow).
2024-06-03 16:41:29 +02:00
SleekZ
8ab8965713 Improved clarity in comment. (#7642) 2024-06-01 09:54:20 +02:00
ocornut
9aec6d7217 Internals: Added ItemUnclipByLog for use by ItemAdd(), as we expected to add more. 2024-05-31 21:38:06 +02:00
ocornut
0fce21e890 Internals: Disable 0xCC stack fill for ItemAdd()/ItemSize(). 2024-05-31 21:38:02 +02:00
ocornut
854e21d4b4 Disabled: move field to ImGuiWindowStackData. (#7640)
Amend f953ebf
2024-05-31 18:24:55 +02:00
Cyao
538960bf17 Examples: Fixed SDL3 Makefile (#7641) 2024-05-31 18:16:45 +02:00
ocornut
f953ebf9ca Disabled: nested tooltips or other non-child window within a BeginDisabled() block disable the disabled state. (#211, #7640) 2024-05-31 18:13:25 +02:00
Rodrigo Rivas Costa
e47015aef4 Demo: remove incompatible ImGuiInputFlags for Shortcut(). (#7637) 2024-05-31 16:30:11 +02:00
ocornut
97a1111b94 Drag and Drop: tweaked BeginDragDropSource() to remove indent. Added debug log. 2024-05-29 18:48:32 +02:00
ocornut
661c388515 Debug Log, Test Engine: avoid duplicate carriage return when using ImGuiDebugLogFlags_OutputToTestEngine. (#5855) 2024-05-29 18:48:28 +02:00
ocornut
868f444620 Debug: extracted debug log 0xXXXXXXX scanning into a helper function. (#5855) 2024-05-29 18:48:25 +02:00
ocornut
109a8632d7 Combo: simplified Combo() API uses a list clipper.
Wasn't as trivial before supporting IncludeItemByIndex().
2024-05-28 18:24:01 +02:00
ocornut
51823d117d Misc: made ImGuiDir, ImGuiSortDirection, ImGuiMouseCursor stronger-typed enums + cater for possible warning in backends's switch()
Not making ImGuiMouseCursor one because of warnings for non-explicitly handled value (case default: is not enough).
2024-05-28 18:09:41 +02:00
ocornut
222dd775fc Merge branch 'master' into docking
# Conflicts:
#	imgui.cpp
#	imgui.h
#	imgui_internal.h
2024-05-28 17:11:57 +02:00
ocornut
5cbc34a10c Scrollbar: clicking above or below the grab scrolls by one page, holding mouse button repeats scrolling. (#7328, #150)
Remove absolute seeking entirely. Amend f02108085.
2024-05-28 16:28:20 +02:00
ocornut
479c5f62fc Style: make DisplayWindowPadding visible in style editor. 2024-05-28 15:47:19 +02:00
ocornut
ed9eb880b5 Windows: Fixed altering FramePadding mid-frame not correctly affecting logic responsible for honoring io.ConfigWindowsMoveFromTitleBarOnly. (#7576, #899)
Latching TitleBarHeight, MenuBarHeight in window.
2024-05-28 15:35:36 +02:00
ocornut
5a1a9a804a Docs: fixed link. 2024-05-28 15:07:07 +02:00
ocornut
7f5d5c80b2 Internals, Tabbar: fixed TabBarGetCurrentTab() with tab_idx == 0. (#7629)
Thanks @VerySmallRoach. Amend 3d8885cbb (#5853, #5997)
2024-05-28 10:11:01 +02:00
ocornut
1f9fc382c3 Version 1.90.8 WIP
Tidying up todo.txt
2024-05-28 10:09:31 +02:00
ocornut
2db79d0868 Merge branch 'master' into docking
# Conflicts:
#	imgui.cpp
2024-05-27 15:47:30 +02:00
ocornut
00ad3c65bc Version 1.90.7 2024-05-27 15:47:04 +02:00
ocornut
f814ef816f Commented out CaptureKeyboardFromApp(), CaptureMouseFromApp(). Commented out obsolete IsKeyPressedMap() from imgui_internal.h (can call IsKeyPressed). Comments 2024-05-27 14:41:02 +02:00
Christian Fillion
b9084949bd Fixed typo in IsMouseDragging and GetMouseDragDelta's documentation. (#7620) 2024-05-25 14:36:48 +02:00
ocornut
86931393a3 Shortcuts: Revert "SetShortcutRouting: require explicit routing. (#456)
This reverts commit a689fa262a.
2024-05-24 17:59:42 +02:00
ocornut
975beafafd Merge branch 'master' into docking 2024-05-24 17:23:58 +02:00
ocornut
7832e6a70e Shortcuts: Routing: fixed mixed keys<>chars filtering not applying on global routes. (#456, #7618) 2024-05-24 17:10:11 +02:00
ocornut
85d982011e Shortcuts: fixed priority of route calculation (higher first). (#456, #7618) 2024-05-24 17:02:10 +02:00
ocornut
fee0210592 Merge branch 'master' into docking 2024-05-24 16:09:29 +02:00
ocornut
ce4e210dcb Shotcuts: renamed ImGuiInputFlags_RouteGlobalOverFocused -> ImGuiInputFlags_RouteOverFocused, ImGuiInputFlags_RouteGlobalOverActive -> ImGuiInputFlags_RouteOverActive in previsiion of using them with a Hovered route. (#456) 2024-05-24 16:07:58 +02:00
ocornut
5ce3d29955 Shortcuts: rename ImGuiInputFlags_RouteGlobalHighest to ImGuiInputFlags_RouteGlobalOverActive, made ImGuiInputFlags_RouteGlobalOverFocused and ImGuiInputFlags_RouteGlobalOverActive flags. (#456) 2024-05-24 15:44:59 +02:00
ocornut
650cb51bf1 Shortcuts: renamed ImGuiInputFlags_RouteActiveItem to ImGuiInputFlags_RouteActive. (#456, #7618)
Amend ef9d525
2024-05-24 15:27:48 +02:00
ocornut
ef9d525f02 Shortcuts: added ImGuiInputFlags_RouteActiveItem. (#456, #7618) + rearrange Changelog 2024-05-24 15:07:43 +02:00
ocornut
16b72f2d21 Comments 2024-05-24 14:21:50 +02:00
ocornut
29439bdd27 Windows: BeginChild(): fixed auto-fit calculation when using either (not both) ResizeX/ResizeY and double-clicking on a border. (#1710)
Calculation incorrectly didn't always account for scrollbar as it assumed the other axis would also be auto-fit.
2024-05-24 12:31:40 +02:00
ocornut
374b9a7fb4 Demo: Documents: refactor + add Renaming option. (#7233) 2024-05-23 21:35:07 +02:00
ocornut
c150ad50c4 Shortcuts: claim mods ownership once pressed. (#456, #2637, #2620, #2891, #3370, #3724, #4828, #5108, #5242, #5641) 2024-05-23 18:14:16 +02:00
ocornut
1002cfa6d2 Demo, Shortcut(): amend Shortcuts demo. (#456) 2024-05-23 18:12:42 +02:00
ocornut
7c71e66370 Shortcuts, SetShortcutRouting: move ImGuiInputFlags_RouteFromRootWindow evaluation to SetShortcutRouting() for now. (#456) 2024-05-23 17:33:16 +02:00
ocornut
5ecef2f321 Merge branch 'master' into docking
# Conflicts:
#	examples/example_win32_directx10/main.cpp
#	examples/example_win32_directx11/main.cpp
#	examples/example_win32_directx12/main.cpp
#	imgui.cpp
2024-05-23 17:25:02 +02:00
ocornut
d5a600e9c6 Shortcuts, SetShortcutRouting: added ImGuiInputFlags_RouteFromRootWindow. Made it possible for SetShortcutRouting() to query for another location. 2024-05-23 17:22:44 +02:00
ocornut
0eb025f484 Internals: move ItemHandleShortcut() next to Shortcut(), it's calling it anyhow. (#456) 2024-05-23 17:17:54 +02:00
ocornut
a689fa262a SetShortcutRouting: require explicit routing. (#456) 2024-05-23 17:09:48 +02:00
ocornut
c06e6340cd Shortcuts: added ImGuiInputFlags_Tooltip. (#456) 2024-05-23 16:58:14 +02:00
ocornut
77e4171894 Shortcuts: added flags to SetNextItemShortcut(). (#456) 2024-05-23 16:57:19 +02:00
ocornut
197f8904fe Shortcuts, Nav: make SetNextItemShortcut() work when another item is active. Made NavCalcPreferredRefPos() take account for remote activation. (#456)
Unsure why filter in ItemHandleShortcut(), will probably find out soon enough.
2024-05-23 16:57:19 +02:00
ocornut
dc5caa483c Demo: added "Shortcuts" section. (#456, #2637) 2024-05-23 16:57:19 +02:00
ocornut
fc512a2474 Inputs: Added Shortcut(), SetNextItemShortcut(). Added ImGuiInputFlags, ImGuiInputFlags_RouteXXXX. (#456, #2637) 2024-05-23 16:57:03 +02:00
ocornut
85513de247 Internals, Inputs: *Breaking* Swapped parameter order of owner-aware versions of IsKeyPressed(), IsKeyChordPressed(), IsMouseClicked(). (#456)
For several reasons those changes makes sense. They are being made because making some of those API public.
Only past users of imgui_internal.h with the extra parameters will be affected.
Added asserts for valid flags in various functions to detect _some_ misuses, BUT NOT ALL.
Amend 4448d975 (#456, #2637, #2620, #2891, #3370, #4828, #5108, #5242, #5641)
2024-05-23 16:57:03 +02:00
ocornut
900b29055c Internals, Inputs: *Breaking* Swapped parameter order of Shortcut(). (#456)
Amend 4448d975 (#456, #2637, #2620, #2891, #3370, #4828, #5108, #5242, #5641)
2024-05-23 16:57:03 +02:00
ocornut
55748cdbe1 Internals, Inputs: *Breaking* Renamed ImGuiKeyOwner_None to ImGuiKeyOwner_NoOwner: avoid confusion with non zero value, makes IsKeyPressed() calls using ImGuiKeyOwner_NoOwner more explicit.
Amend 4448d975 (#456, #2637, #2620, #2891, #3370, #4828, #5108, #5242, #5641)
2024-05-23 16:57:03 +02:00
ocornut
ec1d2be96f Examples: Win32+DX9,DX10,DX11,DX12: rework main loop to handle minimization and screen locking. (#2496, #3907, #6308, #7615) 2024-05-23 15:15:42 +02:00
ocornut
6d1a6f1c74 Internals, Inputs: Comments, alignment. 2024-05-22 12:17:33 +02:00
Michal Šlesár
4c3eac2c10 Backends: OpenGL3: Fixed zealous warning by initializing last_pixel_unpack_buffer. (#7614) 2024-05-22 12:01:54 +02:00
ocornut
36ffdd69d3 Merge remote-tracking branch 'origin/master' into docking 2024-05-21 19:01:06 +02:00
ocornut
9ebab255d2 Docking: *BREAKING* changed signature of DockSpaceOverViewport() to allow passing an explicit dockspace id if desired. (#7611) 2024-05-21 19:00:25 +02:00
ocornut
a1566c5e1b Tables: fixed 28a283b breaking PageDown on tables with no interactive items. 2024-05-21 12:35:22 +02:00
ocornut
aa725ca79d Inputs: moving ImGuiInputFlags_RouteAlways into ImGuiInputFlags_RouteTypeMask_ 2024-05-21 12:28:47 +02:00
ocornut
cd48059dc5 Tables: comments about skipping access to table data in coarse clipping path. 2024-05-21 12:07:50 +02:00
ocornut
28a283b460 Windows: BeginChild(), Tables:fixed visibility of fully clipped child windows and tables to Test Engine. 2024-05-21 11:06:40 +02:00
Eugene Sandulenko
aa5a6098ee Fixed typos in comments (#7599) 2024-05-18 17:10:36 +02:00
ocornut
d39ca33b63 Fixed false positive with PVS-Studio.
Amend ae8218a.
2024-05-17 17:13:55 +02:00
ocornut
ae8218a3ea Inputs, Shortcut: fixes some edge cases for GetKeyChordName(), clarify that it is aimed at display. (#456)
Rename IsNamedKeyOrModKey() to IsNamedKeyOrMod() for consistency.
Fixed GetKeyName(ImGuiKey_None) from returning "N/A" or "None" depending on IMGUI_DISABLE_OBSOLETE_KEYIO.
See "inputs_keychord_name" in imgui_test_suite.
2024-05-17 17:07:50 +02:00
ocornut
25e279ee73 Inputs: Treat ctrl-left-click as right click when ConfigMacOSXBehaviors is set. (#2343) 2024-05-17 15:26:34 +02:00
ocornut
b4f564c1ed Internals: Shortcuts: *Breaking* : rename ImGuiInputFlags_RouteGlobalLow -> ImGuiInputFlags_RouteGlobal, ImGuiInputFlags_RouteGlobal -> ImGuiInputFlags_RouteGlobalOverFocused, ImGuiInputFlags_RouteGlobalHigh -> ImGuiInputFlags_RouteGlobalHighest (#456) 2024-05-17 14:18:22 +02:00
ocornut
b39fc84f89 Merge branch 'master' into docking
# Conflicts:
#	imgui.cpp
2024-05-16 19:57:04 +02:00
ocornut
5107e58b0f Inputs: amend changelog and clarify how the swap might be a breaking change for a minority of users. (#2343) 2024-05-16 19:56:29 +02:00
ocornut
8bd5d1d42f Inputs: Fixed swapping of keys associated to mods. Fixed warnings. (#2343, #4084, #5923, #456)
Amend 7747106.
2024-05-16 19:23:05 +02:00
ocornut
7747106647 Inputs: swap Ctrl and Cmd on macOS X, remove ImGuiMod_Shortcut. (#2343, #4084, #5923, #456) 2024-05-16 19:16:55 +02:00
Hubert Maier
07dbcf1f70 Fixed typos. (#7593) 2024-05-16 16:13:01 +02:00
ocornut
93daf23223 Examples: SDL3: updates for latest SDL3 API changes. 2024-05-15 14:18:48 +02:00
kuvaus
e45efa9951 Backends: SDL3: Rename SDLK_QUOTE and SDLK_BACKQUOTE to SDLK_APOSTROPHE and SDLK_GRAVE. (#7580) 2024-05-15 14:11:54 +02:00
ocornut
5d973a87d4 Backends: SDL_Renderer2/SDL_Renderer3: and ImGui_ImplSDLRenderer2_RenderDrawData() and ImGui_ImplSDLRenderer3_RenderDrawData() now takes a SDL_Renderer* parameter. 2024-05-15 13:44:54 +02:00
Erin M
af2fbf043d Backends/Internals: Don't use IME and clipboard default win32 functions when WINAPI_FAMILY_GAMES (#7585) 2024-05-15 11:42:56 +02:00
ocornut
15d8d41f86 Examples: add missing ImGuiConfigFlags_DockingEnable flag in some examples. 2024-05-14 19:01:18 +02:00
ocornut
eabe98f6d5 Merge branch 'master' into docking (incl merge moved CurrentDpiScale field)
# Conflicts:
#	backends/imgui_impl_osx.mm
#	backends/imgui_impl_win32.cpp
#	imgui.cpp
2024-05-14 16:29:06 +02:00
ocornut
e4576914cb Internals: amend f806c76 to better match docking + fixed unused static forward declaration warning. 2024-05-14 16:22:27 +02:00
ocornut
d0524df887 Internals: slight refactor FindHoveredWindow() -> FindHoveredWindowEx() toward reducing far-away code duplication. 2024-05-14 16:03:00 +02:00
ocornut
f806c76e97 Tables, Dpi: added dummy g.DpiScale storage (to be altered in docking), using to scale tables border hit thickness.
+ Added note about how equivalent resize padding for windows (sourced from WINDOWS_HOVER_PADDING) would need further rework.
2024-05-14 15:03:20 +02:00
omar
f0912833ba Update FAQ.md (#7581) 2024-05-14 14:09:46 +02:00
ocornut
ac90e1bd5b Backends: Win32: replace bd != nullptr assert with early out. (#6275)
+ fixed inconsistent use of break vs return 0 in WndProcHandler (had no tangible effect).
2024-05-14 12:18:10 +02:00
omar
0a5d40a016 Update FAQ.md 2024-05-14 11:40:23 +02:00
ocornut
d06b8b58d8 Nav: fixed holding Ctrl or gamepad L1 from not slowing down keyboard/gamepad tweak speed.
Broken by 8b8a61bd + Comments (#7570)
2024-05-13 19:03:04 +02:00
ocornut
5e23680454 Backends: all backends + demo now call IMGUI_CHECKVERSION() to verify ABI compatibility between caller code and compiled version of dear imgui. (#7568) 2024-05-13 15:07:13 +02:00
prabu
510eb8f480 Tables: fixed cell background of fully clipped row overlapping with header. (#7575, #7041) 2024-05-13 14:50:15 +02:00
ocornut
f48aae600a Version 1.90.7 WIP 2024-05-13 14:47:37 +02:00
ocornut
e391fe2e66 Merge branch 'master' into docking
# Conflicts:
#	backends/imgui_impl_opengl3.cpp
#	imgui.cpp
#	imgui_internal.h
2024-05-08 16:17:32 +02:00
ocornut
6ccc561a2a Version 1.90.6 2024-05-08 15:38:33 +02:00
ocornut
0d483a1c89 Backends: OpenGL3: Update loader for Linux to support EGL/GLVND. (#7562)
+ #6983
2024-05-07 18:23:29 +02:00
ocornut
92df32d339 Backends: OpenGL3: minor update of generated loader to match latest downloaded glcorearb.h/khrplatform.h files. 2024-05-07 17:46:36 +02:00
ocornut
1ab1af80c7 Backends: Win32: Facepalm revert part of d15574c + additional commentary (#6275) 2024-05-07 17:03:51 +02:00
ocornut
d15574ce2a Backends: Win32: Removed silent return when calling ImGui_ImplWin32_WndProcHandler() with no active context! (#6275)
Better standardized similar checks in other backends.
2024-05-07 16:53:03 +02:00
Rory O'Connell
8b2c6dd42f Backends: Vulkan: reworked swap-chain resize handling for secondary viewports to work with typical Linux setups. (#2626, #3390, #3758, #7508, #7513) 2024-05-07 16:14:15 +02:00
ocornut
d4495446d5 Windows, Internal: added experimental SkipRefresh mode. (#3515, #4763, #7556, #5116 , #4076, #2749, #2268)
currently: ImGui::SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags_TryToAvoidRefresh);
- This is NOT meant to replace frame-wide/app-wide idle mode.
- This is another tool: the idea that a given window could avoid refresh and reuse last frame contents.
- I think it needs to be backed by a careful and smart design overall (refresh policy, load balancing, making it easy and obvious to user).
- It's not there yet, this is currently a toy for experimenting.
My other issues with this:
- It appears to be very simple, but skipping most of Begin() logic will inevitably lead to tricky/confusing bugs. Let's see how it goes.
- I don't like very much that this opens a door to varying inconsistencies
- I don't like very much that it can lead us to situation where the lazy refresh gets disabled in bulk due to some reason (e.g. resizing a dock space) and we get sucked in the temptation to update for idle rather than update for dynamism.
2024-05-07 11:44:43 +02:00
cfillion
f5d185238c Viewports: fixed outer-right edge of MenuBar clipping rectangle off by one when window is located on a monitor with negative coordinates. (#6861, #2884) 2024-05-03 17:44:33 +02:00
ocornut
2f2d5070f5 Merge branch 'master' into docking
# Conflicts:
#	imgui.cpp
#	imgui.h
2024-05-03 16:30:09 +02:00
ocornut
0b309471f2 Windows: Changed default ClipRect to extend to windows' left and right borders. (#3312, #7540, #3756, #6170, #6365) 2024-05-03 16:00:20 +02:00
ocornut
0c9c12c1bb InnerClipRect use ImFloor() matching docking branch (fix c41868531 for #6861, #2884, followed by rename 94da5842)
Since negative windows can never be visibile in master it didn't show as a difference.
2024-05-03 15:51:49 +02:00
ocornut
6ebbecc6a0 Realign assignments.
No functional changes.
2024-05-03 12:57:07 +02:00
thedmd
fc4d818e17 Tables: Angled headers: added TableAngledHeadersTextAlign, ImGuiStyleVar_TableAngledHeadersTextAlign. (#6917) 2024-05-03 12:54:59 +02:00
ocornut
4bb7567141 Tables: Angled headers: fixed multi-line label display when angle is flipped. (#6917) 2024-05-02 13:49:26 +02:00
ocornut
b30df8890d Table: Angled Headers: internal refactor to facilitate changing angled header bg and text colors per column. (#6917) 2024-04-30 17:39:52 +02:00
Sandro Cavazzoni
ebb8d78102 Backends: Vulkan: Create a custom pipeline for secondary viewports. (#6325, #6305, #7398, #3459, #3253, #3522)
Edited from original commit: moved ImGui_ImplVulkan_CreatePipeline() call from ImGui_ImplVulkanH_CreateOrResizeWindow() to ImGui_ImplVulkan_CreateWindow().
2024-04-30 15:37:36 +02:00
ocornut
49e70e60a2 Backends: Vulkan: Stripped misleading leftover of ImGui_ImplVulkanH_Window::Pipeline (#6325, #6305, #7398, #3459, #3253, #3522)
As this is currently unused and misleading. Next commit will add a separate pipeline for secondary viewport.
2024-04-30 15:37:36 +02:00
ocornut
9d6818d0ce Docking: comments, clairfy why we store style override on dragged windows. Clarify why we don't need to store alpha. (#7535, #2771)
Amend ebbb98d51
2024-04-30 14:10:11 +02:00
ocornut
558c57a086 Fixed static analyzer warning "Pointer to local array 'overlay_buf' is stored outside the scope". Technically not used outside that scope, but best to play nice. 2024-04-30 11:00:57 +02:00
ocornut
5717f0a33e Merge branch 'master' into docking
# Conflicts:
#	backends/imgui_impl_vulkan.cpp
#	backends/imgui_impl_win32.cpp
2024-04-30 10:42:46 +02:00
ocornut
50b2ff0bf0 ImGuiIO: moved IMGUI_DISABLE_OBSOLETE_KEYIO block lower in the structure so other fields layout are not affected by it (#7534)
This is essentially a misleading grace feature allowing a build mistake to be made, as we technically are more flexible now. BUT if we reintroduce a need we may more harshly move it to the top of the structure to detect issues.
2024-04-30 10:23:03 +02:00
ocornut
6ef4f67fa9 ImDrawList: moved cold fields lower in the structure so hot fields are closer to each others + better packed ImGuiNavItemData 2024-04-30 10:06:42 +02:00
Lukas Lipp
a60387a3c2 Backends: GLFW: Add define guards for glfw native defines. (#7536) 2024-04-29 19:24:17 +02:00
ocornut
913151caa8 Demo: move progress bars to their own section. 2024-04-24 19:40:26 +02:00
gan74
c895e987ad ProgressBar: added indeterminate mode by passing an animated negative value. (#5316, #5370, #1901) 2024-04-24 19:40:26 +02:00
diego.mateos
b8a44b198c TreeNode: added ImGuiTreeNodeFlags_SpanTextWidth. (#6937) 2024-04-24 19:00:58 +02:00
ocornut
baaaaea9e9 Demo: tweak TreeNode demo. 2024-04-24 18:20:09 +02:00
ocornut
da18fcb7ae Internals: ensure ButtonBehavior() is called with non 0 id. 2024-04-23 18:39:40 +02:00
ocornut
b720c0f541 Backends: Vulkan: Added convenience support for Volk via IMGUI_IMPL_VULKAN_USE_VOLK define. (#6582, #4854) 2024-04-19 15:47:26 +02:00
ocornut
07e8ff9a8d Backends: Win32: Fixed a warning + moved header cruft below Changelog. 2024-04-18 21:26:49 +02:00
ocornut
b555984a94 Merge branch 'master' into docking
# Conflicts:
#	backends/imgui_impl_opengl3.cpp
#	imgui.cpp
2024-04-18 21:18:18 +02:00
ocornut
fa0120ea5e Windows: Fixed subsequent Begin() append calls from setting last item information for title-bar. (#7506, #823)
Amend 067605052, 27fd1b913b
2024-04-18 21:17:12 +02:00
ocornut
361432a0bb TreeNode: fixed layout so that TreeNode("") or TreeNode("##HiddenLabel") may properly be used with SameLine(0,0). (#7505, #282)
Also adjust some of the interact_bb padding, arbitrary interact padding not meaningful as empty label is likely to be followed by extra item. User likely to use ImGuiTreeNodeFlags_SpanAvailWidth.
2024-04-18 20:50:00 +02:00
ocornut
eba46cb0d2 Drag and Drop: assert when nesting BeginDragDropSource() and BeginDragDropTarget() (#7504) + update Gallery links 2024-04-17 18:00:55 +02:00
ocornut
9ec299ebe3 Backends: OpenGL: Detect ES3 contexts on desktop based on version string, (#7447) 2024-04-16 16:18:51 +02:00
ocornut
4cb0fe3c7d Merge branch 'master' into docking
# Conflicts:
#	backends/imgui_impl_sdl3.cpp
#	backends/imgui_impl_sdl3.h
#	docs/CHANGELOG.txt
#	imgui_internal.h
2024-04-16 14:24:13 +02:00
ocornut
7b8107e7c8 Examples: GLFW+WebGPU: Rename example_emscripten_wgpu/ to example_glfw_wgpu/ (#7435, #7132) 2024-04-16 14:16:32 +02:00
ocornut
648278cd62 Examples: GLFW+WebGPU: Amends. (#7435, #7132) 2024-04-16 12:33:36 +02:00
Jules Fouchy
80a5fdb108 Examples: GLFW+WebGPU: Fixed condition for when to recreate swapchain. (#7435, #7132) 2024-04-16 11:59:04 +02:00
Elias Daler
f9df6bf662 Examples: GLFW+WebGPU: added support for WebGPU-native/Dawn (#7435, #7132) 2024-04-16 11:59:04 +02:00
GamingMinds-DanielC
b475309fa1 Fonts: Fixed font ascent and descent calculation when a font hits exact integer values. (#7399, #7404) 2024-04-15 15:31:39 +02:00
ocornut
daecfffefb Text, DrawList: Improved handling of long single-line wrapped text. (#7496, #5720) 2024-04-15 12:52:45 +02:00
Green Sky
fab96a6e59 Backends: SDL3: Re-enable calling SDL_StartTextInput()/SDL_StopTextInput(). (#7452, #6306, #6071, #1953)
Amend: a7703fe
2024-04-15 12:25:42 +02:00
ocornut
dad1689bf7 Examples: SDL3: amend for removal of SDL_RENDERER_ACCELERATED. 2024-04-15 12:08:07 +02:00
ocornut
c1743eef48 Docking: when io.ConfigDockingWithShift is enabled, fixed help tooltip erroneously reading SetNextWindowXXX() data. (#6709, #4643, #7491) 2024-04-15 11:43:16 +02:00
ocornut
3caa79c8a5 Version 1.90.6 WIP 2024-04-15 11:27:07 +02:00
ocornut
76bc1b825e Extracted part of NewFrame() into SetupDrawListSharedData() for documentation purpose. (#7495, #6406)
Also changed g.Font->ContainerAtlas->Flags to g.IO.Fonts->Flags
2024-04-15 11:24:43 +02:00
ocornut
f790d51665 Silent zealous/stupid warning introduced by Clang 16 (shipping with VS2022) with -Weverything. Pointers are now illegal! 2024-04-12 16:55:32 +02:00
ocornut
1db579d458 Merge branch 'master' into docking 2024-04-11 16:21:56 +02:00
ocornut
231cbee0fc Version 1.90.5 2024-04-11 15:54:39 +02:00
GamingMinds-DanielC
4f9ba19e52 Drags, Sliders, Inputs: Reactivated decimal point replacement for SliderScalar and DragScalar. (#7389, #6719, #2278)
Amend/fix 4a242644
2024-04-03 11:39:46 +09:00
ocornut
e7712ff103 Out of courtesy/consistency move all the DebugHookIdInfo compares into ifndef block. 2024-04-03 10:50:32 +09:00
ocornut
f959c417fe Refactor moving ID stack functions to their own section (part 2) 2024-04-03 10:48:32 +09:00
ocornut
0bf134a8e2 Refactor moving ID stack functions to their own section. 2024-04-03 10:42:57 +09:00
ocornut
9a2b598ec1 ListBox: Fixed text-baseline offset when using SameLine()+Text() after a labeled ListBox().
Visible in demo->basic->listbox
2024-04-03 10:20:18 +09:00
ocornut
d3c3514a59 Tables: Fixed auto-width columns when using synced-instances of same table. (#7218) 2024-03-29 19:39:05 +09:00
ocornut
25a492f330 ProgressBar: Fixed passing fraction==NaN from leading to a crash. (#7451) 2024-03-29 19:09:55 +09:00
ocornut
9638c2839a Internals: adding ImGuiNavMoveFlags_NoClearActiveId even though there's currently no satisfying way to take advantage of it. (#1418) 2024-03-27 12:00:50 +09:00
ocornut
742e53434f Child Windows: adjust resizing limits to match window padding rather than inner clipping rectangle. (#7440) 2024-03-27 11:36:57 +09:00
cfillion
515b437c08 Child windows: look at the parent window's flags to decide whether to clamp child resizes. (#7440, #1710) 2024-03-27 11:24:07 +09:00
cfillion
976dc23965 Windows: extend outer resize borders to the edges when there are no corner grips. (#7440, #1710) 2024-03-27 11:01:14 +09:00
ocornut
37b37fc2a3 DrawList: Allow AddText() to accept null ranges. (#3615, 7391) 2024-03-27 10:51:42 +09:00
ocornut
5c5ae806aa Comments 2024-03-26 14:42:51 +09:00
cfillion
cf4c10bef7 Style: added ImGuiStyleVar_TabBorderSize, ImGuiStyleVar_TableAngledHeadersAngle. (#7411) 2024-03-26 14:38:38 +09:00
cfillion
f0802287db Tables: Angled headers: fixed table contents overflowing when a list clipper is used. (#7416) 2024-03-26 13:01:24 +09:00
cfillion
29ff159f94 Tables: Angled headers: fixed borders not moving back up after TableAngleHeadersRow stops being called. (#7416) 2024-03-26 13:01:24 +09:00
cfillion
38ddfb24f0 Tables: Angled headers: fixed border hit box extending beyond non-scrollable tables. (#7416) 2024-03-26 13:01:24 +09:00
Elie Michel
8be48a44f7 Backends: WebGPU: Avoid using -1u literal (#7436) 2024-03-25 11:10:38 +09:00
ocornut
085781f5ca Merge branch 'master' into docking
# Conflicts:
#	imgui.cpp
2024-03-18 22:52:40 -07:00
cfillion
868facff9d ImDrawList: (Breaking) merge float radius_x/radius_y parameters into ImVec2 radius in PathEllipticalArcTo(), AddEllipse(), AddEllipseFilled(). (#2743, #7417) 2024-03-18 22:50:47 -07:00
Christian Fillion
0a1f5b94e3 Demo: Two minor fixes (unchecked BeginTooltip + incorrect height constraint) (#7410)l 2024-03-17 23:29:10 -07:00
ocornut
40df3db1a2 Tweaking terminology 2024-03-17 19:46:12 +09:00
ocornut
adcc3217c3 Revert "Docking: Fix C++26 zealous warnings (#7383, #7089)" + Disable warnings
This reverts commit 9d9ca37a84.
2024-03-11 15:07:05 +01:00
ocornut
9d9ca37a84 Docking: Fix C++26 zealous warnings (#7383, #7089) 2024-03-11 14:41:02 +01:00
Robert Edmonds
da29b776ee Backends: SDL3: Fix leak of SDL_GetGamepads() return value (#7381) 2024-03-11 11:04:56 +01:00
ocornut
3c435c0297 Inputs: (Breaking) More formally obsoleted GetKeyIndex() when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is set. (#4921) 2024-03-08 12:16:24 +01:00
ocornut
286cd5bd41 Internals, InputText: removed ImGuiInputSource_Clipboard. (#4005)
Added by f08566b4d
2024-03-07 15:02:38 +01:00
Kevin Leonardic
fc570ac922 Examples: WGPU: fixed initialization of WGPURenderPassColorAttachment (#7371) 2024-03-06 13:44:37 +01:00
ocornut
fd75685fb0 Merge branch 'master' into docking 2024-03-05 18:12:11 +01:00
ocornut
65dc67f63c Windows: Double-click to collapse may be disabled via key-ownership mechanism. (#7369) 2024-03-05 17:34:34 +01:00
ocornut
6b7358e9f3 InputText: adding clarifying note about ImGuiInputTextCallbackData::Buf. (#7363) 2024-03-04 11:30:22 +01:00
ocornut
fbf45ad149 ImDrawList: add PathFillConcave(), AddConcavePolyFilled(): amends (#760)
- Simplify and compact some code. Shallow tweaks.
- Add comments.
- Add concave shape demo.
- Remove coarse culling.
- Remove nested types to match coding style and for consistent type nams when translated to other languages.
- Merged ClassifyNode() and ReclassifyNode().
- Extracted ImTriangleIsClockwise().
- Hold copy of points inside nodes instead of pointing to them.
2024-03-01 21:08:18 +01:00
thedmd
1ff90c52d5 ImDrawList: add PathFillConcave(), AddConcavePolyFilled() (#760)
Extracted from 2023/12/29 post.
WIP add PathFillConcave(), AddConcavePolyFilled()
* remove use of 'auto'
* IsConvex -> ImPathIsConvex
* Triangulator -> ImTriangulator
* ImTriangulator: split declaration from definition, ImTriangulator can be put in the header if necessary
* ImTriangulator: Add node list flip to reverse winding order and handle degenerate cases
* ImTriangulator: Remove _HeapStorage, always require scratch buffer to be provided
* ImTriangulator: Use ImTriangleContainsPoint
* AddConcavePolyFilled: Clone AddConvexPolyFilled and use triangulator
* AddConcavePolyFilled: Remove ImDrawListEx_AddPolyFilled_xxx
* AddConcavePolyFilled: Use _Data->TempBuffer in triangulator
* AddConcavePolyFilled:
2024-03-01 21:06:00 +01:00
ocornut
04f40014a6 Docs: added a mini wiki index in main source files. 2024-02-29 15:17:08 +01:00
omar
c623669967 Added link to crawlable wiki 2024-02-28 19:21:13 +01:00
ocornut
0573513d6d Windows: Scrollbar visibility decision uses current size when both size and contents size are submitted by API. (#7252) 2024-02-28 17:09:20 +01:00
ocornut
77dff5a735 Backends: comments. 2024-02-28 11:06:40 +01:00
ocornut
4e8c43f6b7 Backends: Win32: made it so that an appearing viewport showing up doesn't bring its parent viewport to front. (#7354) 2024-02-27 20:02:26 +01:00
ocornut
44c7dfca03 Menus, Popup: Amend c3f8f4d for static analyzer warning ("condition always true"). (#7325) 2024-02-27 19:42:20 +01:00
ocornut
1a487165b1 Merge branch 'master' into docking 2024-02-27 18:44:51 +01:00
ocornut
c3f8f4de25 Menus, Popups: Fixed an issue where sibling menu popups re-opening in successive frames would erroneously close the window. (#7325, #7287, #7063)
Amend 014e0ac8
2024-02-27 18:36:46 +01:00
ocornut
9877941775 Popups, Menus: rename ImGuiPopupData::BackupNavWindow > RestoreNavWindow and minor tweaks. Should be functionally a no-op.
This is expected to clear the noise so next commit can be cleared to read. (#7325)
Last renamed in b3ea01d86
2024-02-27 17:56:51 +01:00
GamingMinds-DanielC
725f91922d Tables: fixed TableGetHoveredRow() with overlapping frozen rows (#7350, #6588, #6347, #6250) 2024-02-26 13:33:41 +01:00
ocornut
e46d1e69ac Version 1.90.5 WIP 2024-02-26 13:31:10 +01:00
ocornut
c6aa051629 Merge branch 'master' into docking
# Conflicts:
#	imgui.cpp
2024-02-22 20:01:46 +01:00
ocornut
277ae93c41 Version 1.90.4 2024-02-22 19:56:39 +01:00
ocornut
f5be90523d Nav: Fixed SetKeyboardFocusHere() or programmatic tabbing API from not working on windows with the ImGuiWindowFlags_NoNavInputs flag.
Amend/fix 13d91ff 3a078466
2024-02-22 19:43:03 +01:00
ocornut
13d91ff918 Nav: Fixed SetKeyboardFocusHere() or programmatic tabbing API from not working on windows with the ImGuiWindowFlags_NoNavInputs flag.
Amend/fix 3a078466a
2024-02-22 19:39:10 +01:00
ocornut
34965cf23a Modals: Temporary changes of ImGuiCol_ModalWindowDimBg are properly handled by BeginPopupModal(). (#7340)
+ Misc: Added optional alpha multiplier parameter to GetColorU32(ImU32) variant.
2024-02-22 14:53:33 +01:00
ocornut
659fb41d0a Debug Tools: moved DebugStartItemPicker() to public API. Added to Demo->Tools menu. (#2673) 2024-02-20 17:33:17 +01:00
ocornut
198c38f0b1 Demo: Custom Rendering: better demonstrate PathArcTo(), PathBezierQuadraticCurveTo(), PathBezierCubicCurveTo(), PathStroke(), PathFillConvex() functions. 2024-02-20 16:33:54 +01:00
ocornut
3b6d924acd ProgressBar: Fixed a minor tesselation issue when rendering rounded progress bars.
Incidentally, the auto-tesselation path of PathArcTo() wasn't much tested.
2024-02-20 16:02:04 +01:00
ocornut
2b662b1ab9 Merge branch 'master' into docking
# Conflicts:
#	docs/CHANGELOG.txt
#	imgui.cpp
2024-02-20 15:33:20 +01:00
ocornut
d3f1a7165c Popups: allow Child Popups to be resizable if not explicitly disabling. 2024-02-20 15:03:09 +01:00
ocornut
e78ce72eb6 Popups: Fixed resizable popup minimum size being too small. Standardized CalcWindowMinSize() logic a bit more. (#73290
Amend e2035a514, 623bff23ce, 923535240, etc.
2024-02-20 15:00:01 +01:00
ocornut
014e0ac8c9 Menus, Popups: Fixed an issue where hovering a parent-menu upward would erroneously close the window. (#7325, #7287, #7063)
Amend 76e09c4b0. Initial call to ClosePopupToLevel d31fe97f7 (#2880).
See "widgets_menu_reopen_2" in TestSuite.
2024-02-20 14:01:24 +01:00
ocornut
c16043c1d5 Tables: Angled headers: improve clipping of text since multi-line labels makes clipping issues visible. (#6917) 2024-02-19 20:49:52 +01:00
ocornut
405e54ebd5 Tables: Angled Headers: fixed support for multi-line labels. various padding/layout fixes. (#6917) 2024-02-19 20:27:20 +01:00
ocornut
6655ab2e43 Tables: Angled Headers: fixed TableAngledHeadersRow() incorrect background fill drawn too low. Fixed row geometry with non-small values of CellPadding. (#6917) 2024-02-19 19:08:38 +01:00
Tim-Rex
9159cd7b4a Updated invalid documentation link (#7331) 2024-02-18 12:51:32 +01:00
cvionis
ccc5347e45 Fix typos (#7332) 2024-02-18 12:50:51 +01:00
ocornut
8a14b71f22 Version 1.90.4 WIP 2024-02-15 16:51:57 +01:00
John Melas
b19a4c5f2b Backends: OSX: remove legacy clearing of io.NavInputs in ImGui_ImplOSX_UpdateGamepads(). (#7320) 2024-02-15 14:57:37 +01:00
ocornut
8048b52498 Backends: GLFW: enable ImGuiBackendFlags_HasMouseHoveredViewport support with GLFW 3.3.x. (#7316) 2024-02-15 14:50:45 +01:00
ocornut
c66a1e7d51 Backends: Vulkan: ImGui_ImplVulkan_CreateWindow() amend merge to take account of PipelineRenderingCreateInfo change. (#7166, #6855, #5446, #5037) 2024-02-14 14:39:26 +01:00
ocornut
d79514c407 Merge branch 'master' into docking
# Conflicts:
#	backends/imgui_impl_dx9.cpp
#	backends/imgui_impl_sdl2.cpp
#	backends/imgui_impl_sdl3.cpp
#	backends/imgui_impl_vulkan.cpp
#	imgui.cpp
2024-02-14 14:32:17 +01:00
ocornut
5b6f03213d Version 1.90.3 2024-02-14 13:58:19 +01:00
Shawn Hatori
f80e65a406 Backends:,Examples: Vulkan: moved RenderPass parameter from ImGui_ImplVulkan_Init() function to ImGui_ImplVulkan_InitInfo structure. (#7308) 2024-02-14 13:56:46 +01:00
ocornut
829f45df99 Backends: SDL2: removed obsolete ImGui_ImplSDL2_NewFrame(SDL_Window*) signature which was obsoleted in 1.84.. 2024-02-14 12:06:21 +01:00
Tom Seddon
3cc37170ca Examples: GLFW+Metal: Add -I and -L paths for MacPorts. 2024-02-14 11:47:02 +01:00
ocornut
891b81fc5d Backends: SDL3: Fixed gamepad. Added support for disconnection. Added support for multiple gamepads. Added ImGui_ImplSDL3_SetGamepadMode(). (#7180, #3884, #6559, #6890) 2024-02-14 11:37:18 +01:00
ocornut
262e30e300 Backends: SDL2: rework new API as ImGui_ImplSDL2_SetGamepadMode(). (#3884, #6559, #6890, #7180)
Code is simpler this way.
2024-02-14 11:30:43 +01:00
ocornut
9dfa2397de Internals: Fixed ImFileOpen not working before context is created. (#7314, #7315)
Amend daf49e9d8
2024-02-14 11:02:24 +01:00
ocornut
d15e4100b8 Backends: SDL2: Amend new API, all support for multiple gamepads. (#3884, #6559, #6890) 2024-02-13 18:55:14 +01:00
ocornut
f966da1f8f Backends: SDL2: Gamepad handlng: amend bf1c96d. (#3884, #6559, #6890) 2024-02-13 16:31:33 +01:00
ocornut
bf1c96d4fa Backends: SDL2: Handle gamepad disconnection + fixed increasing refcount. Added ImGui_ImplSDL2_SelectGamepadAuto()/ImGui_ImplSDL2_SelectGamepadExplicit(). (#3884, #6559, #6890) 2024-02-13 16:24:44 +01:00
ocornut
fd8d6dc5d1 Backends: SDL2,SDL3: tidying up. 2024-02-13 15:49:49 +01:00
ocornut
e0ba0d0433 Backends: Vulkan: Fixes for building with pre Vulkan 1.3. Amend 8901931. (#7166) 2024-02-12 18:46:01 +01:00
ocornut
11d73f03ee Backends: Vulkan: Fix/amend 8901931 2024-02-12 17:18:52 +01:00
Shawn Hatori
89019319dd Backends: Vulkan: use PipelineRenderingCreateInfo for dynamic rendering (#7166, #6855, #5446, #5037) 2024-02-12 16:55:00 +01:00
璀境石
1d6f0cea0e Backends: DX9: use RGBA texture to avoid conversion if supported 2024-02-12 16:05:10 +01:00
ocornut
3af739a2d1 Menus, Popups: fixed menus and popups with child window flag erroneously not displaying a scrollbar when contents is over parent viewport size. (#7287, #7063)
Amend f37f6f6
2024-02-12 15:21:48 +01:00
ocornut
2af01baffd Backends: SDLRenderer3: query newly added SDL_RenderViewportSet() to not restore a wrong viewport if none was initially set.
https://github.com/libsdl-org/SDL/issues/9029
2024-02-12 14:57:39 +01:00
ocornut
915c6393ad Version 1.90.3 WIP 2024-02-12 14:54:48 +01:00
ocornut
8490a262c4 Debug Tools: Metrics: Improved Monitors and Viewports minimap display. Highlight on hover. (amends) 2024-02-09 17:28:41 +01:00
ocornut
71bcf350bd Merge branch 'master' into docking
# Conflicts:
#	imgui.cpp
2024-02-09 17:26:45 +01:00
ocornut
536090303a Version 1.90.2 2024-02-09 16:59:31 +01:00
ocornut
7b5357d817 Debug Tools: Metrics: Improved Monitors and Viewports minimap display. Highlight on hover.
Added ImGuiViewport ID in Master branch.
2024-02-09 16:32:26 +01:00
ocornut
30ba3c347c Viewports: Fixed moving accross monitors when io.ConfigWindowsMoveFromTitleBarOnly is set. (#7299, #3071) 2024-02-09 15:43:25 +01:00
ocornut
59c8db69eb Demo: reorder Demo->Configuration section with docking/viewports section. 2024-02-09 15:27:35 +01:00
ocornut
70aa717a8e Combo: Fixed not reusing windows optimally when used inside a popup stack. 2024-02-09 15:23:43 +01:00
ocornut
5cdc4a2a41 Demo: use ImGui::MemAlloc/MemFree for consistency. (#7300) 2024-02-09 14:20:12 +01:00
ocornut
76e09c4b0f ClosePopupsOverWindow(): amend to remove _ChildWindow test.
Said test seems unnecessary and incorrect as we test hierarchy now. See test "nav_ctrl_tab_popups" in ImGuiTestSuite.
2024-02-08 17:08:01 +01:00
ocornut
3a078466a7 Nav: ImGuiWindowFlags_NoNavInputs is tested during scoring so NavFlattened windows can use it. 2024-02-08 16:06:55 +01:00
ocornut
7d67623d15 InputText: Internal: ReloadUserBufXXX functions don't override revert value. (#2890) fix accidental comment. 2024-02-08 15:46:17 +01:00
ocornut
a5e0e90c16 Nav: tweak RenderNavHighlight() syntax. ImGuiNavHighlightFlags_TypeThin -> ImGuiNavHighlightFlags_Compact. 2024-02-08 15:44:46 +01:00
ocornut
1e8fc01ddd InputText: Internal: ReloadUserBufXXX functions don't override revert value. (#2890) + rename 2024-02-08 15:25:04 +01:00
ocornut
a06dd7a27b OpenPopup(): Added ImGuiPopupFlags_NoReopen. Nav, Menus: Fixed click on a BeginMenu() followed by right-arrow. (#1497, #1533)
reopen
2024-02-08 15:02:22 +01:00
ocornut
f104967c68 Comments 2024-02-08 12:10:14 +01:00
ocornut
82eeafc196 Merge branch 'master' into docking
# Conflicts:
#	backends/imgui_impl_glfw.cpp
2024-02-07 22:10:33 +01:00
ocornut
06ce312745 InputText: Internal: added reload from user-buf feature. (#2890)
Very highly requested feature (#6962, #5219, #3290, #4627, #5054, #3878, #2881, #1506, #1216, #968).
Also useful for interactive completion/selection popups (#2057, #718)
Based on @kudaba PR. Design for Inputtext V2 should make this obsolete.
2024-02-07 22:04:18 +01:00
Bruce Mitchener
f50ddc431e Fixed some typos. (#7282) 2024-02-01 18:30:00 +01:00
Bruce Mitchener
6172c22c5d CI: Update to actions/checkout v4 from v3. (#7281) 2024-02-01 16:07:29 +01:00
ocornut
96839b445e Nav: Improve handling of Alt key to toggle menu so that key ownership may be claimed on indiviudal left/right alt key without intefering with the other.
See test "inputs_owner_single_mod"
2024-01-25 16:51:07 +01:00
ocornut
7194756370 Shortcut: fixed single mod-key Shortcut from working e.g. Shortcut(ImGuiKey_LeftCtrl) 2024-01-25 15:42:19 +01:00
Peter0x44
f1960b60c1 Added "nop" to IM_DEBUG_BREAK macro on GCC to work around GDB bug (#7266)
There are two issues here - first, this macro uses AT&T specific syntax with $, which is not necessary. Also, some assemblers (nasm) emit different bytes for "int 3" and "int3", so it's better to use "int3" (cd 03 vs cc)

More importantly, GDB has some failing assertion whenever stepping after hitting an "int3" instruction. This makes it practically useless, as is. For some reason, putting a nop afterwards as a workaround is okay.

Related discussions:
https://sourceware.org/bugzilla/show_bug.cgi?id=31194
https://lists.sr.ht/~skeeto/public-inbox/%3C2d3d7662a361ddd049f7dc65b94cecdd%40disroot.org%3E
2024-01-25 11:48:16 +01:00
ocornut
8491cf36ad Inputs: g.ActiveIdUsingManyKeys[] prevent routes from being claimed.
Amend fc134f5
2024-01-24 18:53:36 +01:00
ocornut
9176eedf24 Internals: SetShortcutRouting() move code so next commit is easier to read. Should be no-op. 2024-01-24 18:51:00 +01:00
ocornut
1509842107 Backends: OpenGL3: Shallow tweak of compile-time extensions detection.
Detect polygon mode using same method as others (not define/symbol).
IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS -> IMGUI_IMPL_OPENGL_HAS_EXTENSIONS
2024-01-24 15:21:46 +01:00
Clément Gallet
1ce41f6218 Backends: OpenGL3: Backup and restore GL_PIXEL_UNPACK_BUFFER. (#7253)
Amended with (bd->GlVersion >= 210) checks.
2024-01-24 15:01:59 +01:00
actboy168
54ef4092a9 Backends: OSX: Fixed not submitting Monitors info when viewports are not enabled. (#7257) 2024-01-24 14:51:04 +01:00
ocornut
81e0be856a Fixed strict-aliasing violation in FormatTextureIDForDebugDisplay(). (#7090, #7256) 2024-01-24 14:27:43 +01:00
ocornut
eb42e164dd Merge branch 'master' into docking
# Conflicts:
#	backends/imgui_impl_vulkan.cpp
2024-01-22 19:01:25 +01:00
ocornut
a201af7354 Added SetNextItemShortcut() wip function. (#456)
Mark widget as hovered. Amend d10641b.
2024-01-22 18:38:54 +01:00
ocornut
4c2c09450a Nav: keyboard/gamepad activation feedback properly timed instead of frame buffer. (#456)
Amend d10641b
2024-01-22 18:26:45 +01:00
ocornut
5b5e9bd0cb Internals: Tweak shallow compaction as Clang complains about MS ABI signage of enums. 2024-01-22 17:43:58 +01:00
ocornut
7c3fa7d049 Refactor: moved section in imgui_internal.h 2024-01-22 17:42:00 +01:00
rajveermalviya
9266c0d2d1 Backends: WebGPU: Avoid leaking pipeline layout. (#7245) 2024-01-22 15:37:00 +01:00
ocornut
595eb86624 Changelog, comment, minor data compaction 2024-01-22 15:27:36 +01:00
ocornut
6850194f60 CI: Fixes WGPU example build. 2024-01-22 15:01:21 +01:00
ocornut
5fc0a361b2 Backends: WebGPU: added ImGui_ImplWGPU_InitInfo::PipelineMultisampleState. (#7240) 2024-01-22 14:54:45 +01:00
ocornut
831d42c1ab Backends: WebGPU: ImGui_ImplWGPU_Init() now takes a ImGui_ImplWGPU_InitInfo structure instead of variety of parameters, allowing for easier further changes. (#7240) 2024-01-22 14:53:30 +01:00
ocornut
e3c7ff944d Examples: Emscripten+WebGPU: slightly refactor like other Emscripten compatible Desktop examples, as aiming to make this suppot desktop eventually.
Also aimed at reducing diff for https://github.com/ocornut/imgui/pull/7132 tho this will lead in conflict.
2024-01-22 14:37:53 +01:00
Frank McCoy
15908502ed Backends: Vulkan: Define NOMINMAX when VK_USE_PLATFORM_WIN32_KHR is defined. (#7250) 2024-01-22 11:15:14 +01:00
Michał Cichoń
788747f863 Examples: Emscripten+WebGPU: Remove use of deprecated ObjectBase<...>::Release in favor of ::MoveToCHandle (#7251) 2024-01-22 10:45:41 +01:00
ocornut
763100b385 Nav: Fixed pressing Escape while in a child window with _NavFlattened flag. (#7237) 2024-01-19 18:37:21 +01:00
ocornut
c7edb446ca Shortcut(): always test ownership.
- It doesn't sense to test route without ownership (which may be overrided by code not using routing)
- It also wouldn't be possible to call Shortcut() with _None anyway, since successful routing sets ownership.
Tangential to experiments for #7237
2024-01-19 16:40:24 +01:00
ocornut
1844f903d5 Nav: space/enter poll check ownership. InputText: declare ownership of Enter key as it doesn't go through Shortcut
InputText: no need to call SetShortcutRouting() directly.
Tangential to experiments for #7237
2024-01-19 16:22:45 +01:00
ocornut
5ddfbb80d8 Backends: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236) 2024-01-19 14:52:33 +01:00
ocornut
01b99a974d Backends: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236) 2024-01-19 14:50:46 +01:00
ocornut
2f48337335 Examples: Vulkan: Rename compile-time defies for the examples to remove misleading IMGUI_ prefixes. 2024-01-19 14:50:38 +01:00
ocornut
cab7edd135 Merge branch 'master' into docking
# Conflicts:
#	imgui_internal.h
2024-01-17 18:38:03 +01:00
ocornut
d7c2a0e38f Shortcut(): fixed 8323a06 adding _Repeat to all Shortcut() calls. 2024-01-17 18:21:04 +01:00
ocornut
3b828d3701 Refactor: moving ItemAdd() into a section abote ItemSize(). No logic change (part 2)
Diff not ideal (in Fork it looks like ItemSize is moved) but understandable at a glance.
2024-01-17 17:34:28 +01:00
ocornut
ff5f3aa38b Refactor: moving ItemAdd() into a section abote ItemSize(). No logic change (part 1)
Moved KeepAliveID() as well for increased locality.
Adding dummy ItemAdd() placeholder to facilitate diffing (otherwise single commit single diff is a mess).
2024-01-17 17:32:50 +01:00
ocornut
1a48a63446 Enclosed a few more remaining sections in ifndef IMGUI_DISABLE_DEBUG_TOOLS for completeness. 2024-01-17 15:55:36 +01:00
ocornut
33fabdf392 Scrollbar() doesn't forcefully mark itself as hovered when held.
Weirdly as old as when dinosaurs roamed earth, aka first commit (per-1.0).
+ Minor alignment in both sense of the term :) Reduce padding in ImGuiNextItemData.
2024-01-17 15:47:14 +01:00
ocornut
d431d85839 Internals: removed obsolete ImPool::GetSize() (last used by implot 0.10, changed in implot 0.11) 2024-01-17 15:33:12 +01:00
ocornut
f0d1f61fa5 Internals: commented out long-time obsoleted FocusableItemRegister()/FocusableItemUnregister() documentaton-only leftovers. + 2024-01-17 15:23:30 +01:00
ocornut
095665977f Nav: marking NavId as hovered in ButtonBehavior() doesn't check for ActiveId.
Aimed at allowing activating another item with a shortcut without losing NavId.
Initial logic from c2cb2a69, with minor amends db5f1b79c, cea78cc57.
2024-01-17 14:52:05 +01:00
ocornut
d10641b04a Nav: keyboard/gamepad activation mark widgets as held to give better visual feedback. 2024-01-17 14:02:07 +01:00
ocornut
03417cc77d Backends: WebGPU: Filling all WGPUDepthStencilState fields explicitly as a recent Dawn update stopped setting default values. (#7232) 2024-01-17 13:26:02 +01:00
ocornut
5fdcdf7080 Shortcut: ImGuiInputFlags_RouteFocused policy can filter Shortcuts conflicting with character input when an item is active. (#456) 2024-01-16 17:51:14 +01:00
ocornut
80d5cb1ab1 Comments around ImGuiInputFlags. 2024-01-16 16:25:08 +01:00
ocornut
80c83a4277 Docking: added ImGuiDockNodeFlags_DockedWindowsInFocusRoute to configure a dock node to automatically set ParentWindowForFocusRoute on its docked windows. (#6798, #2637, #456) 2024-01-16 14:30:43 +01:00
ocornut
cceff4684a Docking: added ImGuiWindowClass::FocusRouteParentWindowId as a public facing version of SetWindowParentWindowForFocusRoute() (#6798, #2637, #456) 2024-01-16 14:30:42 +01:00
ocornut
1cc0eb4d32 Internals: Rename NavFocusScopePath to NavFocusRoute + fixed a static analyzer warning. 2024-01-16 12:32:00 +01:00
ocornut
69b64e2b73 Internals: Docking: revert 32a3c61 in favor of user explicitely calling SetWindowParentWindowForFocusRoute(). (#6798)
The revert doesn't look the same as 32a3c61 as since then we are baking focus roue into NavFocusScopePath().
2024-01-16 11:50:00 +01:00
ocornut
a27f22f0e9 Merge branch 'master' into docking
# Conflicts:
#	backends/imgui_impl_vulkan.cpp
#	imgui.cpp
#	imgui_internal.h
2024-01-16 11:43:36 +01:00
ocornut
46e5f44ec8 Shortcut()/SetShortcutRouting(): use mixed current window focus scope + ParentWindowForFocusRoute. (#6798, #2637, #456)
Amend d474836
Begin: tweak clearing of CurrentWindow as FocusWindow() relies on it now.
Addded SetWindowParentWindowForFocusRoute() helper.
2024-01-16 11:39:41 +01:00
ocornut
e0c8c80ada Shortcut()/SetShortcutRouting(): focus route testing now use ParentWindowForFocusRoute. Automatically set on child-window, manually configurable otherwise. (#6798, #2637, #456) 2024-01-15 17:33:47 +01:00
ocornut
4b20a0217e Internals: add window to FocusScopeStack. (#6798) 2024-01-15 17:33:47 +01:00
ocornut
2156db7a07 Debug Log: added InputRouting logging. Made GetKeyChordName() use its own buffer. Fixed debug break in SetShortcutRouting(). (#6798, #2637, #456) 2024-01-15 17:33:23 +01:00
ocornut
dd0efdc637 Fixed SetKeyboardFocusHere() not working when current nav focus is in different scope. (#7226)
Amend 70f2aaff
2024-01-15 17:32:11 +01:00
ocornut
8a3dfda8d0 Commented out obsolete ImGuiIO::ImeWindowHandle marked obsolete in 1.87, favor of writing to 'void* ImGuiViewport::PlatformHandleRaw'.
Amend 3a90dc38 (#2589, #2598, #3108, #3113, #3653, #4642)
2024-01-15 11:30:52 +01:00
ocornut
6228c2e1ec Backends: Vulkan: moved ImGui_ImplVulkanH_DestroyFrameRenderBuffers/ImGui_ImplVulkanH_DestroyWindowRenderBuffers as they are always used in a state where backend data is available. 2024-01-11 20:22:37 +01:00
ocornut
32a3c61d00 Internals: Shortcut() follow docking chain (until we formalize a more general focus scope stack). (#456) 2024-01-11 19:48:31 +01:00
ocornut
70bb6d1e79 Backends: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size. (#3957) 2024-01-11 14:57:38 +01:00
Tristan Gouge
82df7c8bf4 Backends: Vulkan: Fixed handling of ImGui_ImplVulkan_InitInfo::MinAllocationSize field. (#7189, #4238) 2024-01-11 14:43:51 +01:00
ocornut
29809d7220 Version 1.90.2 WIP 2024-01-11 14:37:13 +01:00
ocornut
db049db860 Docs: tweak, fixed misplaced changelog entry. (#7084) 2024-01-11 13:14:21 +01:00
ocornut
2dc85e6e43 Merge branch 'master' into docking
# Conflicts:
#	backends/imgui_impl_opengl3.cpp
#	imgui.cpp
#	imgui_internal.h
2024-01-10 18:34:23 +01:00
ocornut
d6cb3c923d Version 1.90.1 2024-01-10 18:00:57 +01:00
ocornut
6470e2279e Debug Tools: DebugRenderKeyboardPreview() scales better. 2024-01-10 17:35:41 +01:00
ocornut
fdf8d02be1 Debug Tools: Added io.ConfigDebugIsDebuggerPresent and Debug Break buttons. (#2673) 2024-01-10 17:33:19 +01:00
ocornut
788bb58b6b Metrics: Tweak, reorganize tools menu. 2024-01-10 15:12:24 +01:00
ocornut
a5dec42866 Debug Tools: Debug Log: Clicking any filter with SHIFT held enables it for 2 frames only. (#5855) 2024-01-10 15:12:24 +01:00
ocornut
a3eea8a75a Backends: OpenGL3: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" and variants, fixing regression on distros missing a symlink. (#6983)
Amend 0f50b52da
2024-01-09 23:26:05 +01:00
ocornut
cf02023565 Internals, Inputs: Fix for ImGuiInputFlags_RepeatUntilXXX logic when #ifdef IMGUI_DISABLE_OBSOLETE_KEYIO is not set.
Amend 8323a06. Eager to get rid of legacy IMGUI_DISABLE_OBSOLETE_KEYIO stuff: technically it's been two years, may give it another one.
2024-01-09 23:05:53 +01:00
ocornut
69bf3291df Internals, Inputs: Fix for ImGuiInputFlags_RepeatUntilXXX logic when #ifdef IMGUI_DISABLE_OBSOLETE_KEYIO is not set.
Amend 8323a06. Eager to get rid of legacy IMGUI_DISABLE_OBSOLETE_KEYIO stuff: technically it's been two years, may give it another one.
2024-01-09 23:05:45 +01:00
ocornut
ebcfcd8da3 Merge branch 'master' into docking 2024-01-09 22:39:06 +01:00
ocornut
8deb1007cd Backends: OSX: Fixed IME position in multi-monitor/multi-viewports setups. (#7028) 2024-01-09 22:36:01 +01:00
ocornut
a683033e49 Backends: OSX: Fixed monitor and window position by correctly transforming Y origin on multi-monitor setups. (#7028, #7101, #6009, #6432) 2024-01-09 22:21:57 +01:00
ocornut
af00b182e3 Examples: SDL3: Minor fixes following changes to API (SDL_WindowFlags -> Uint32).
"The SDL_WindowFlags enum should be replaced with Uint32"
2024-01-09 16:04:48 +01:00
ocornut
fc2e532f99 Shortcut: do not return true on mods changes. Internals: added ImGuiInputFlags_RepeatUntilKeyModsChange, ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone, ImGuiInputFlags_RepeatUntilOtherKeyPress. (#456, #2637)
Took a while to come to this design, but it is flexible and lightweight and allow all decision to be taken a polling location. All three policies are useful.
2024-01-09 15:54:12 +01:00
ocornut
8323a06e6d Inputs: passing ImGuiInputFlags_RepeatXXX options automatically adds ImGuiInputFlags_Repeat.
Will make extra sense with next commit where we add ImGuiInputFlags_RepeatUntil options.
2024-01-09 12:09:42 +01:00
ocornut
58261dbe9a Internals: alter ImGuiInputFlags values to leave room + indent. 2024-01-09 12:06:58 +01:00
ocornut
f1ae47c4b9 Docs: update links to Proggy Fonts. (#7211) 2024-01-09 12:06:58 +01:00
ocornut
7f9533b840 ColorPicker: Fixed saturation/value cursor radius not scaling properly.
+ Misc docs/comments.
2024-01-08 16:08:12 +01:00
Tom Seddon
27e83c2953 Add comment about how ImGuiKey values are named after US keyboard keys. (#7205)
General text input is already covered by AddInputCharacter. For scancode-based key up/down info, simplest to admit that the up/down state indexes are kind of arbitrary and may not actually map perfectly to the labels on the keys.
2024-01-08 11:37:38 +01:00
ocornut
278cf1a7bc Readme: updated binaries. (#7193)
+ removed two now unnecessary casts.
2024-01-05 16:47:39 +01:00
omar
edeb8ee3ab More compact issue_template.yml 2024-01-05 11:42:22 +01:00
uusdnfdsfhnttyh
c6716f5e9f Fixed typo (#7197) 2024-01-05 10:11:08 +01:00
ocornut
a1b06823fe Windows: BeginChild(): Resize borders rendered even when ImGuiWindowFlags_NoBackground is specified. (#1710, #7194) 2024-01-04 17:23:30 +01:00
ocornut
0461ade24b Reworked issue template (amends) (#5927, #5915) 2024-01-04 16:53:26 +01:00
ocornut
c528b688cf Reworked issue template. (#5927, #5915) 2024-01-04 16:38:58 +01:00
omar
26eef4df87 Update issue_template.md 2024-01-04 15:15:48 +01:00
ocornut
7938550d52 Comments and some extra line-wrapping in demo (#3193) 2024-01-04 11:50:38 +01:00
Pascal Thomet
4758f74676 imgui_freetype: fix nullptr to ImTextureID cast (#7192) 2024-01-03 22:54:36 +01:00
ocornut
e3d7cd665d Merge branch 'master' into docking
# Conflicts:
#	backends/imgui_impl_glfw.cpp
#	backends/imgui_impl_vulkan.cpp
2024-01-03 18:33:44 +01:00
ocornut
6f10cef2a1 Backends: Vulkan: moved structure declarations.
This is mostly to facilitate maintainance of #6616.
2024-01-03 16:19:03 +01:00
ocornut
33d18c580b Misc: During shutdown, check that io.BackendPlatformUserData and io.BackendRendererUserData are NULL. (#7175) 2024-01-03 14:56:21 +01:00
ocornut
0ea99132c8 Backends: Vulkan: Stop creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT as we don't reset them. 2024-01-03 14:11:40 +01:00
Tristan Gouge
4778560e66 Backends: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous validation layer. (#7189, #4238) 2024-01-03 12:17:08 +01:00
Axel Paris
e8dd47effa Backends: WebGPU: Fixing an issue when opening a popup in the wgpu backend (#7191)
Amend 2b0bd40b9
2024-01-03 12:05:37 +01:00
ocornut
718fa0eec6 Happy new year! 2024-01-02 22:03:36 +01:00
David Maas
2523c197bc Fixed title bar background alpha being used to render viewport-owned windows. (#7184, #7181) 2023-12-31 00:45:25 +01:00
kida22
240ab5890b Backends: GLFW, Input: Use Unicode version of WndProc for get correct input for text in utf-8 code page. (#7174)
Similar to #6785, #6782, #5725, #5961 for for GLFW backend.
2023-12-29 18:21:21 +01:00
ocornut
4a2426449a Drags, Sliders, Inputs: removed all attempts to filter non-numerical characters during text editing. (#6810, #7096) 2023-12-22 19:51:49 +01:00
Kai Wang
20e1caec85 Backends: DX12: Changed swapchain scaling mode to DXGI_SCALING_NONE. (#7152, #7153) 2023-12-21 14:18:43 +01:00
ocornut
f039e69b9c Settings: Fixed an issue marking settings as dirty when merely clicking on a border or resize grip without moving it. 2023-12-21 14:14:39 +01:00
ocornut
4aa81116a5 Merge branch 'master' into docking
# Conflicts:
#	backends/imgui_impl_glfw.cpp
#	imgui.cpp
2023-12-20 23:57:19 +01:00
ocornut
8340a30d27 Debug: move debug assertion in post-clip code to reduce overhead. (#4796 and more).
Amend c80179921
2023-12-20 16:23:27 +01:00
ocornut
1e1013085b Debug Tools: Debug Log: Hide its own clipper log to reduce noise in the output. 2023-12-20 16:22:35 +01:00
ocornut
036a6c875e ColorEdit4: Further tweaks for very small sizes. (#7120, #7121) 2023-12-20 11:06:22 +01:00
ocornut
0bd6489721 DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: fixed multi-components width in tight space (#7120, #7121)
+ extra tweak color ColorEdit4() label. Amend 86512ea, 3464662
2023-12-19 20:50:17 +01:00
ocornut
0000739c08 Internals: Fixed function name typo. 2023-12-19 20:32:09 +01:00
ocornut
33d426842d Backends: Vulkan: ImGui_ImplVulkan_CreateFontsTexture() calls vkQueueWaitIdle() instead of vkDeviceWaitIdle(). (#7148, #6943, #6715, #6327, #3743, #4618) 2023-12-19 18:25:09 +01:00
ocornut
3cb805489b Backends: GLFW, Emscripten: fixes for canvas resizing, amends. (#6751)
Amend 22a7d24
2023-12-19 16:09:44 +01:00
Pello Rao
22a7d241ff Backends: GLFW, Emscripten: fixes for canvas resizing. (#6751) 2023-12-19 15:56:31 +01:00
ocornut
b4c5a83cfe Commented out obsolete ImGuiKey_KeyPadEnter redirection to ImGuiKey_KeypadEnter. (#2625, #7143) 2023-12-19 13:55:09 +01:00
ocornut
70f2aaff43 Nav: tabbing happen within FocusScope. ImGuiWindowFlags_NavFlattened make window inherit focus scope from parent. 2023-12-19 13:48:04 +01:00
ocornut
55073aa7a3 Examples; SDL: added missing return values checks from SDL_CreateWindow() calls. (#7147) 2023-12-19 11:22:43 +01:00
ocornut
8764a1b7c4 Backends: Vulkan: free FontCommandBuffer explicitely (not actually required in normal code path, unless ImGui_ImplVulkan_DestroyDeviceObjects is declared directly). (#7104) 2023-12-19 10:51:15 +01:00
Kevin Coghlan
089ed30323 Replace usages of ImGuiKey_KeyPadEnter with ImGuiKey_KeypadEnter. (#7143) 2023-12-19 00:30:49 +01:00
ocornut
e265610a0c Fixes for MSVC code analyzer. 2023-12-18 18:36:01 +01:00
ocornut
f59b54c6f4 Nav: Activation can also be performed with Keypad Enter. (#5606) 2023-12-18 18:23:53 +01:00
ocornut
0d582dabf3 Fixed warning (amend 54c1bde) 2023-12-14 17:24:23 +01:00
ocornut
8add6bcb9f Merge remote-tracking branch 'origin/master' into docking
# Conflicts:
#	imgui.cpp
#	imgui.h
2023-12-14 17:21:15 +01:00
ocornut
6cfe3ddf52 InputTextMultiline: Tabbing through a multi-line text editor using ImGuiInputTextFlags_AllowTabInput doesn't activate it. (#3092, #5759, #787) 2023-12-14 17:15:43 +01:00
ocornut
54c1bdeceb Internals: removed unused ImGuiItemStatusFlags_FocusedByTabbing. (#4449)
Amend 1a7526d
2023-12-14 16:45:40 +01:00
ocornut
4afffa36e9 InputTextMultiline: Fixed Tab character input not repeating
(1.89.4 regression)
2023-12-14 16:31:18 +01:00
ocornut
f6836ff37f Misc: Rework debug display of texture id in Metrics window (amend) (#7090)
Amend 96b5b17
2023-12-12 18:24:30 +01:00
ocornut
07dbd46ddd Misc: Rework debug display of texture id in Metrics window to avoid compile-error when ImTextureID is defined to be larger than 64-bits. (#7090) 2023-12-12 18:18:52 +01:00
Nahor
34646627aa ColorEdit4: improve components width computation to better distribute the error (#7120) (#7123) 2023-12-12 11:07:01 +01:00
Nahor
86512eac06 DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: improve multi-components width computation to better distribute the error. (#7120, #7121) 2023-12-12 00:34:18 +01:00
ocornut
03298fe875 Windows: Fixed some auto-resizing path using style.WindowMinSize.x (instead of x/y). (#7106) 2023-12-10 12:53:20 +01:00
ocornut
69f524ba95 DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: Added when component <= 0. (#7095) 2023-12-08 18:43:29 +01:00
ocornut
9d8de45313 Image(): comment and minor refactor to resurface the fact that a border size may be added. (#2118)
Make more similar to ImageButton()
2023-12-07 16:07:50 +01:00
ocornut
5366bd09bf Scrolling: internal scrolling value is rounded instead of truncated. (#6677) 2023-12-07 15:47:18 +01:00
ocornut
c58d2c89c3 Tabs: Added ImGuiTabItemFlags_NoAssumedClosure to enable app to react on closure attempt. (#7084) 2023-12-07 14:20:35 +01:00
ocornut
1fade35159 DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: Fixed incorrect pushes into ItemWidth stack when number of components is 1. [#7095] 2023-12-07 14:01:53 +01:00
ocornut
58ca5f6424 Shortcut(): clearer early out in SetShortcutRouting() -> CalcRoutingScore() path. 2023-12-06 16:15:11 +01:00
ocornut
d72e1563d4 Removed CalcListClipping() marked obsolete in 1.86. (#3841) + comments
Amend 64daeddf
2023-12-06 15:10:12 +01:00
Anılcan Gülkaya
9a2985611c Backend: Android: Remove Redundant Check (#7093) 2023-12-06 04:29:40 +01:00
ocornut
0b77980cab Moved Tables API related declarations to their own section in imgui.h 2023-12-05 18:13:04 +01:00
ocornut
aaf157cfdd Commented out ImGuiFreeType::BuildFontAtlas() obsoleted in 1.81. Commented out legacy ImGuiColumnsFlags_XXX symbols redirecting to ImGuiOldColumnsFlags_XXX, obsoleted in 1.80.
Amend 9499afdf and 72de6f336
2023-12-05 17:04:19 +01:00
ocornut
96b5b1724b Merge branch 'master' into docking
# Conflicts:
#	backends/imgui_impl_vulkan.cpp
#	imgui_internal.h
2023-12-05 12:20:16 +01:00
Johel Ernesto Guerrero Peña
1fd5ff7152 Avoid C++26 removed deprecated arithmetic conversion on enumerations. (#7088, #7089. #2983, #3040) 2023-12-05 12:13:08 +01:00
Bryce Berger
52886872f1 Misc: Added IMGUI_USER_H_FILENAME to change the path included when using IMGUI_INCLUDE_IMGUI_USER_H. (#7039) 2023-12-01 14:26:21 +01:00
ocornut
5768de79e2 InputText, ColorEdit, ColorPicker: better support for undocumented ImGuiItemFlags_ReadOnly flag. (#7079, #211)
Amend fdc526e8f
2023-12-01 13:57:28 +01:00
ocornut
b112d73edb Menus: amend to clarify/fix static analyzer warning. (#6671, #6926) 2023-11-29 17:08:06 +01:00
ocornut
2ee40d3cf9 Menus: Tweaked hover slack logic, adding a timer to avoid situations where a slow vertical movements toward another parent BeginMenu() can keep the wrong child menu open. (#6671, #6926) 2023-11-29 16:46:21 +01:00
ocornut
b4b864e40a Backends: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs vkDestroyCommandPool(). (#7075) 2023-11-29 14:24:25 +01:00
ocornut
d2b0167610 Fixed link error when using IMGUI_DISABLE_DEBUG_TOOLS 2023-11-29 14:09:39 +01:00
ocornut
7965494ff3 Debug Tools: Added DebugFlashStyleColor() to identify a style color. Added to Style Editor. 2023-11-28 19:40:38 +01:00
ocornut
c1a3c7f445 Fixed Clang zealous warnings 2023-11-28 19:33:10 +01:00
ocornut
c6ec69c7c1 Using nullptr in remaining examples/backends locations. (#6313, #7071, #4537) 2023-11-28 19:29:17 +01:00
ocornut
888834c636 Backends: Android: Fixed build breaking typo. (#7060)
Amend 86891b0. My bad for not testing this.
2023-11-28 15:23:45 +01:00
ocornut
077e4db772 Misc: Added extra courtesy ==/!= operators when IMGUI_DEFINE_MATH_OPERATORS is defined. 2023-11-28 15:00:32 +01:00
ocornut
f6253b87d0 Merge branch 'master' into docking
# Conflicts:
#	backends/imgui_impl_sdl3.cpp
#	imgui.cpp
2023-11-28 14:39:46 +01:00
ocornut
6f171a066d Nav, IO: SetNextFrameWantCaptureKeyboard(false) calls are not overrided back to true when navigation is enabled. (#6997) 2023-11-28 14:28:19 +01:00
Marc Delorme
e07663d9a1 Docking: transform ImGuiContext* ctx = GImGui to ImGuiContext& g = *GImGui for consistency (#5856) 2023-11-28 14:18:52 +01:00
Chris Gregory
1f3090a48d Backends: SDL3: Fix indent (#7062) 2023-11-28 12:09:07 +01:00
ocornut
86891b0986 Backends: Android: ImGui_ImplAndroid_HandleInputEvent() takes a const AInputEvent* (#7060) 2023-11-28 12:08:05 +01:00
ocornut
f37f6f67f6 Windows: BeginChild(): Fixed auto-resizing erroneously limiting size to host viewport minus padding. (#7063) 2023-11-27 16:33:20 +01:00
ocornut
bce4db00bc Drag and Drop: Fixed drop target highlight on items temporarily pushing a widened clip rect. (#7049, #4281, #3272) 2023-11-22 19:30:16 +01:00
sakiodre
65a10410e3 Docs: Add suggestion to turn of char8_t behavior for C++20 (#7025) 2023-11-22 19:09:14 +01:00
ocornut
61b8197942 Misc: Renamed some defines in imstb_textedit.h to avoid conflicts when using unity/jumbo builds.
Bitting the bullet, as we rarely update this (and it is rarely updated) and it we may replace it anyhow.
2023-11-22 14:12:31 +01:00
ocornut
3733b5064e Backends: SDL3: Fixed unused variable warning on master on some targets. (#7000) 2023-11-17 12:28:25 +01:00
codefrog2002
c5c1c4134b Backends: OpenGL3: imgui_impl_opengl3_loader.h: change #define ARRAY_SIZE to GL3W_ARRAY_SIZE to avoid external conflicts (#7017, #7018) 2023-11-16 01:38:47 +01:00
ocornut
7bb0a525c3 Fixed text functions fast-path for handling "%s" and "%.*s" to handle null pointers gracefully. (#7016, #3466, #6846) 2023-11-16 00:00:26 +01:00
ocornut
3d083dbe1a Version 1.90.1 WIP 2023-11-15 23:53:58 +01:00
84 changed files with 6785 additions and 3406 deletions

2
.github/FUNDING.yml vendored
View File

@@ -1 +1 @@
custom: ['https://github.com/ocornut/imgui/wiki/Sponsors']
custom: ['https://github.com/ocornut/imgui/wiki/Funding']

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1 @@
blank_issues_enabled: false

View File

@@ -0,0 +1,90 @@
name: "Ask a question, report a bug, request a feature, etc."
description: "Ask any question, discuss best practices, report a bug, request a feature."
body:
- type: markdown
attributes:
value: |
FOR FIRST-TIME USERS ISSUES COMPILING/LINKING/RUNNING or LOADING FONTS, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions)
For anything else: we are happy to use 'GitHub Issues' for many types of open-ended questions. We are encouraging 'Issues' becoming a large, centralized and cross-referenced database of Dear ImGui contents.
Be mindful that messages are being sent to the e-mail box of "Watching" users. Try to proof-read your messages before sending them. Edits are not seen by those users.
- type: markdown
attributes:
value: |
**Prerequisites:**
- I have read [Frequently Asked Questions](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md).
- I have read [Contributing Guidelines -> General Advices](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#getting-started--general-advice).
- I have read [Contributing Guidelines -> How to open an Issue](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#how-to-open-an-issue).
- I have searched [Github Issues and PR](https://github.com/ocornut/imgui/issues?q=) for discussion of similar topics.
----
- type: input
id: specs_version
attributes:
label: "Version/Branch of Dear ImGui:"
description: "(please specify if you have made substantial modifications to your copy)"
value: "Version 1.XX, Branch: XXX (master/docking/etc.)"
placeholder: "Version 1.XX, Branch: XXX (master/docking/etc.)"
validations:
required: true
- type: input
id: specs_backend
attributes:
label: "Back-ends:"
description: (or specify when using custom engine/back-ends)
value: "imgui_impl_XXX.cpp + imgui_impl_XXX.cpp"
placeholder: "imgui_impl_XXX.cpp + imgui_impl_XXX.cpp or n/a"
validations:
required: true
- type: input
id: specs_compiler_os
attributes:
label: "Compiler, OS:"
placeholder: "e.g. Windows 11 + MSVC 2022, macOS + Clang 12, Linux + GCC etc."
validations:
required: true
- type: textarea
id: specs_full
attributes:
label: "Full config/build information:"
placeholder: |
(If you can run, you may go to 'Demo->Tools->About Dear ImGui->Config/Build Info' to obtain detailed information that you can paste here)
validations:
required: false
- type: textarea
id: issue_description
attributes:
label: "Details:"
description: "Try to be explicit with your goals, your expectations and what you have tried. Be mindful of [The XY Problem](https://xyproblem.info). What you have in mind or in your code is not obvious to other people. People frequently discuss problems and suggest incorrect solutions without first clarifying their goals. When requesting a new feature, please describe the usage context (how you intend to use it, why you need it, etc.). If you tried something and it failed, show us what you tried. If you are reporting a bug, explain what's the bug, how does it occur, etc. If you are reporting a crash, please include a debugger callstack."
value: |
**My Issue/Question:**
XXX _(please provide as much context as possible)_
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: "Screenshots/Video:"
description: "Attach screenshots or gif/videos to clarify the context. They often convey useful information that is omitted by the description."
placeholder: "(You can drag files here)"
validations:
required: false
- type: textarea
id: repro_code
attributes:
label: "Minimal, Complete and Verifiable Example code:"
description: "Provide an [MCVE](https://stackoverflow.com/help/mcve) to demonstrate your problem. An ideal submission includes a small piece of code that anyone can paste into one of the examples applications (examples/*/main.cpp) or the demo (imgui_demo.cpp) to understand and reproduce it. Narrowing your problem to its shortest and purest form is the easiest way to understand it, explain it and fix it. Please test your shortened code to ensure it exhibits the problem. Often while creating the MCVE you will solve the problem! Many questions that are missing a standalone verifiable example are missing the actual cause of their issue in the description, which ends up wasting everyone's time."
value: |
```cpp
// Here's some code anyone can copy and paste to reproduce your issue
ImGui::Begin("Example Bug");
MoreCodeToExplainMyIssue();
ImGui::End();
```
validations:
required: false
- type: markdown
attributes:
value: |
Thank you for taking the time to read prerequisites, filling this template and double-checking your message and your code!

View File

@@ -1,46 +0,0 @@
(Click "Preview" above ^ to turn URL into clickable links)
1. FOR FIRST-TIME USERS PROBLEMS COMPILING/LINKING/RUNNING or LOADING FONTS, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions). EVERYTHING ELSE CAN BE POSTED HERE!
2. PLEASE CAREFULLY READ: [FAQ](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md)
3. PLEASE CAREFULLY READ: [Contributing Guidelines](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md)
4. PLEASE MAKE SURE that you have: read the FAQ; explored the contents of `ShowDemoWindow()` including the Examples menu; searched among Issues; used your IDE to search for keywords in all sources and text files; and read the links above.
5. Be mindful that messages are being sent to the e-mail box of "Watching" users. Try to proof-read your messages before sending them. Edits are not seen by those users.
6. Delete points 1-6 and PLEASE FILL THE TEMPLATE BELOW before submitting your issue.
Thank you!
----
_(you may also go to Demo>About Window, and click "Config/Build Information" to obtain a bunch of detailed information that you can paste here)_
**Version/Branch of Dear ImGui:**
Version: XXX
Branch: XXX _(master/viewport/docking/etc.)_
**Back-end/Renderer/Compiler/OS**
Back-ends: imgui_impl_XXX.cpp + imgui_impl_XXX.cpp _(or specify if using a custom engine/back-end)_
Compiler: XXX _(if the question is related to building or platform specific features)_
Operating System: XXX
**My Issue/Question:**
XXX _(please provide as much context as possible)_
**Screenshots/Video**
XXX _(you can drag files here)_
**Standalone, minimal, complete and verifiable example:** _(see https://github.com/ocornut/imgui/issues/2261)_
```
// Here's some code anyone can copy and paste to reproduce your issue
ImGui::Begin("Example Bug");
MoreCodeToExplainMyIssue();
ImGui::End();
```

View File

@@ -21,7 +21,7 @@ jobs:
VS_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\
MSBUILD_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Dependencies
shell: powershell
@@ -209,7 +209,7 @@ jobs:
Linux:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Dependencies
run: |
@@ -402,7 +402,7 @@ jobs:
MacOS:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Dependencies
run: |
@@ -462,7 +462,7 @@ jobs:
iOS:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build example_apple_metal
run: |
@@ -472,7 +472,7 @@ jobs:
Emscripten:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Dependencies
run: |
@@ -489,17 +489,17 @@ jobs:
popd
make -C examples/example_sdl2_opengl3 -f Makefile.emscripten
- name: Build example_emscripten_wgpu
- name: Build example_glfw_wgpu
run: |
pushd emsdk-master
source ./emsdk_env.sh
popd
make -C examples/example_emscripten_wgpu
make -C examples/example_glfw_wgpu -f Makefile.emscripten
Android:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build example_android_opengl3
run: |

View File

@@ -12,7 +12,7 @@ jobs:
PVS-Studio:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 1

3
.gitignore vendored
View File

@@ -40,8 +40,9 @@ examples/*.o.tmp
examples/*.out.js
examples/*.out.wasm
examples/example_glfw_opengl3/web/*
examples/example_glfw_wgpu/web/*
examples/example_glfw_wgpu/external/*
examples/example_sdl2_opengl3/web/*
examples/example_emscripten_wgpu/web/*
## JetBrains IDE artifacts
.idea

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2014-2023 Omar Cornut
Copyright (c) 2014-2024 Omar Cornut
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -28,7 +28,7 @@
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).
// 2022-01-17: Inputs: always calling io.AddKeyModsEvent() next and before key event (not in NewFrame) to fix input queue with very low framerates.
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
// 2021-12-08: Renderer: Fixed mishandling of the the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86.
// 2021-12-08: Renderer: Fixed mishandling of the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86.
// 2021-08-17: Calling io.AddFocusEvent() on ALLEGRO_EVENT_DISPLAY_SWITCH_OUT/ALLEGRO_EVENT_DISPLAY_SWITCH_IN events.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-05-19: Renderer: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
@@ -424,6 +424,7 @@ static ImGuiKey ImGui_ImplAllegro5_KeyCodeToImGuiKey(int key_code)
bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
// Setup backend capabilities flags
@@ -491,8 +492,9 @@ static void ImGui_ImplAllegro5_UpdateKeyModifiers()
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* ev)
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplAllegro5_Init()?");
ImGuiIO& io = ImGui::GetIO();
switch (ev->type)
{
@@ -587,7 +589,7 @@ static void ImGui_ImplAllegro5_UpdateMouseCursor()
void ImGui_ImplAllegro5_NewFrame()
{
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplAllegro5_Init()?");
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplAllegro5_Init()?");
if (!bd->Texture)
ImGui_ImplAllegro5_CreateDeviceObjects();

View File

@@ -157,7 +157,7 @@ static ImGuiKey ImGui_ImplAndroid_KeyCodeToImGuiKey(int32_t key_code)
}
}
int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event)
int32_t ImGui_ImplAndroid_HandleInputEvent(const AInputEvent* input_event)
{
ImGuiIO& io = ImGui::GetIO();
int32_t event_type = AInputEvent_getType(input_event);
@@ -184,7 +184,7 @@ int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event)
case AKEY_EVENT_ACTION_UP:
{
ImGuiKey key = ImGui_ImplAndroid_KeyCodeToImGuiKey(event_key_code);
if (key != ImGuiKey_None && (event_action == AKEY_EVENT_ACTION_DOWN || event_action == AKEY_EVENT_ACTION_UP))
if (key != ImGuiKey_None)
{
io.AddKeyEvent(key, event_action == AKEY_EVENT_ACTION_DOWN);
io.SetKeyEventNativeData(key, event_key_code, event_scan_code);
@@ -222,25 +222,27 @@ int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event)
{
case AMOTION_EVENT_ACTION_DOWN:
case AMOTION_EVENT_ACTION_UP:
{
// Physical mouse buttons (and probably other physical devices) also invoke the actions AMOTION_EVENT_ACTION_DOWN/_UP,
// but we have to process them separately to identify the actual button pressed. This is done below via
// AMOTION_EVENT_ACTION_BUTTON_PRESS/_RELEASE. Here, we only process "FINGER" input (and "UNKNOWN", as a fallback).
if((AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_FINGER)
|| (AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_UNKNOWN))
int tool_type = AMotionEvent_getToolType(input_event, event_pointer_index);
if (tool_type == AMOTION_EVENT_TOOL_TYPE_FINGER || tool_type == AMOTION_EVENT_TOOL_TYPE_UNKNOWN)
{
io.AddMousePosEvent(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
io.AddMouseButtonEvent(0, event_action == AMOTION_EVENT_ACTION_DOWN);
}
break;
}
case AMOTION_EVENT_ACTION_BUTTON_PRESS:
case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
{
int32_t button_state = AMotionEvent_getButtonState(input_event);
io.AddMouseButtonEvent(0, (button_state & AMOTION_EVENT_BUTTON_PRIMARY) != 0);
io.AddMouseButtonEvent(1, (button_state & AMOTION_EVENT_BUTTON_SECONDARY) != 0);
io.AddMouseButtonEvent(2, (button_state & AMOTION_EVENT_BUTTON_TERTIARY) != 0);
}
{
int32_t button_state = AMotionEvent_getButtonState(input_event);
io.AddMouseButtonEvent(0, (button_state & AMOTION_EVENT_BUTTON_PRIMARY) != 0);
io.AddMouseButtonEvent(1, (button_state & AMOTION_EVENT_BUTTON_SECONDARY) != 0);
io.AddMouseButtonEvent(2, (button_state & AMOTION_EVENT_BUTTON_TERTIARY) != 0);
break;
}
case AMOTION_EVENT_ACTION_HOVER_MOVE: // Hovering: Tool moves while NOT pressed (such as a physical mouse)
case AMOTION_EVENT_ACTION_MOVE: // Touch pointer moves while DOWN
io.AddMousePosEvent(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
@@ -262,6 +264,8 @@ int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event)
bool ImGui_ImplAndroid_Init(ANativeWindow* window)
{
IMGUI_CHECKVERSION();
g_Window = window;
g_Time = 0.0;

View File

@@ -30,7 +30,7 @@ struct ANativeWindow;
struct AInputEvent;
IMGUI_IMPL_API bool ImGui_ImplAndroid_Init(ANativeWindow* window);
IMGUI_IMPL_API int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event);
IMGUI_IMPL_API int32_t ImGui_ImplAndroid_HandleInputEvent(const AInputEvent* input_event);
IMGUI_IMPL_API void ImGui_ImplAndroid_Shutdown();
IMGUI_IMPL_API void ImGui_ImplAndroid_NewFrame();

View File

@@ -16,7 +16,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-05-19: DirectX10: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
@@ -540,6 +540,7 @@ void ImGui_ImplDX10_InvalidateDeviceObjects()
bool ImGui_ImplDX10_Init(ID3D10Device* device)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
@@ -588,7 +589,7 @@ void ImGui_ImplDX10_Shutdown()
void ImGui_ImplDX10_NewFrame()
{
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplDX10_Init()?");
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX10_Init()?");
if (!bd->pFontSampler)
ImGui_ImplDX10_CreateDeviceObjects();

View File

@@ -16,7 +16,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
@@ -552,6 +552,7 @@ void ImGui_ImplDX11_InvalidateDeviceObjects()
bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
@@ -605,7 +606,7 @@ void ImGui_ImplDX11_Shutdown()
void ImGui_ImplDX11_NewFrame()
{
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplDX11_Init()?");
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX11_Init()?");
if (!bd->pFontSampler)
ImGui_ImplDX11_CreateDeviceObjects();

View File

@@ -25,7 +25,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-05-19: DirectX12: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
@@ -777,6 +777,7 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO
D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
@@ -833,7 +834,7 @@ void ImGui_ImplDX12_Shutdown()
void ImGui_ImplDX12_NewFrame()
{
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplDX12_Init()?");
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX12_Init()?");
if (!bd->pPipelineState)
ImGui_ImplDX12_CreateDeviceObjects();
@@ -899,7 +900,7 @@ static void ImGui_ImplDX12_CreateWindow(ImGuiViewport* viewport)
sd1.SampleDesc.Quality = 0;
sd1.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
sd1.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
sd1.Scaling = DXGI_SCALING_STRETCH;
sd1.Scaling = DXGI_SCALING_NONE;
sd1.Stereo = FALSE;
IDXGIFactory4* dxgi_factory = nullptr;

View File

@@ -16,7 +16,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-02-12: DirectX9: Using RGBA format when supported by the driver to avoid CPU side conversion. (#6575)
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-06-25: DirectX9: Explicitly disable texture state stages after >= 1.
@@ -297,6 +298,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
@@ -330,6 +332,24 @@ void ImGui_ImplDX9_Shutdown()
IM_DELETE(bd);
}
static bool ImGui_ImplDX9_CheckFormatSupport(IDirect3DDevice9* pDevice, D3DFORMAT format)
{
IDirect3D9* pd3d = nullptr;
if (pDevice->GetDirect3D(&pd3d) != D3D_OK)
return false;
D3DDEVICE_CREATION_PARAMETERS param = {};
D3DDISPLAYMODE mode = {};
if (pDevice->GetCreationParameters(&param) != D3D_OK || pDevice->GetDisplayMode(0, &mode) != D3D_OK)
{
pd3d->Release();
return false;
}
// Font texture should support linear filter, color blend and write to render-target
bool support = (pd3d->CheckDeviceFormat(param.AdapterOrdinal, param.DeviceType, mode.Format, D3DUSAGE_DYNAMIC | D3DUSAGE_QUERY_FILTER | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, format)) == D3D_OK;
pd3d->Release();
return support;
}
static bool ImGui_ImplDX9_CreateFontsTexture()
{
// Build texture atlas
@@ -341,18 +361,21 @@ static bool ImGui_ImplDX9_CreateFontsTexture()
// Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices)
#ifndef IMGUI_USE_BGRA_PACKED_COLOR
if (io.Fonts->TexPixelsUseColors)
const bool rgba_support = ImGui_ImplDX9_CheckFormatSupport(bd->pd3dDevice, D3DFMT_A8B8G8R8);
if (!rgba_support && io.Fonts->TexPixelsUseColors)
{
ImU32* dst_start = (ImU32*)ImGui::MemAlloc((size_t)width * height * bytes_per_pixel);
for (ImU32* src = (ImU32*)pixels, *dst = dst_start, *dst_end = dst_start + (size_t)width * height; dst < dst_end; src++, dst++)
*dst = IMGUI_COL_TO_DX9_ARGB(*src);
pixels = (unsigned char*)dst_start;
}
#else
const bool rgba_support = false;
#endif
// Upload texture to graphics system
bd->FontTexture = nullptr;
if (bd->pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bd->FontTexture, nullptr) < 0)
if (bd->pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, rgba_support ? D3DFMT_A8B8G8R8 : D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bd->FontTexture, nullptr) < 0)
return false;
D3DLOCKED_RECT tex_locked_rect;
if (bd->FontTexture->LockRect(0, &tex_locked_rect, nullptr, 0) != D3D_OK)
@@ -365,7 +388,7 @@ static bool ImGui_ImplDX9_CreateFontsTexture()
io.Fonts->SetTexID((ImTextureID)bd->FontTexture);
#ifndef IMGUI_USE_BGRA_PACKED_COLOR
if (io.Fonts->TexPixelsUseColors)
if (!rgba_support && io.Fonts->TexPixelsUseColors)
ImGui::MemFree(pixels);
#endif
@@ -397,7 +420,7 @@ void ImGui_ImplDX9_InvalidateDeviceObjects()
void ImGui_ImplDX9_NewFrame()
{
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplDX9_Init()?");
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX9_Init()?");
if (!bd->FontTexture)
ImGui_ImplDX9_CreateDeviceObjects();

View File

@@ -10,9 +10,8 @@
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// Issues:
// [ ] Platform: Multi-viewport support: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
// 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.
@@ -24,7 +23,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2023-12-19: Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to register canvas selector and auto-resize GLFW window.
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys.
// 2023-07-18: Inputs: Revert ignoring mouse data on GLFW_CURSOR_DISABLED as it can be used differently. User may set ImGuiConfigFLags_NoMouse if desired. (#5625, #6609)
// 2023-06-12: Accept glfwGetTime() not returning a monotonically increasing value. This seems to happens on some Windows setup when peripherals disconnect, and is likely to also happen on browser + Emscripten. (#6491)
@@ -90,11 +90,15 @@
#ifdef _WIN32
#undef APIENTRY
#ifndef GLFW_EXPOSE_NATIVE_WIN32
#define GLFW_EXPOSE_NATIVE_WIN32
#endif
#include <GLFW/glfw3native.h> // for glfwGetWin32Window()
#endif
#ifdef __APPLE__
#ifndef GLFW_EXPOSE_NATIVE_COCOA
#define GLFW_EXPOSE_NATIVE_COCOA
#endif
#include <GLFW/glfw3native.h> // for glfwGetCocoaWindow()
#endif
@@ -137,7 +141,7 @@ enum GlfwClientApi
{
GlfwClientApi_Unknown,
GlfwClientApi_OpenGL,
GlfwClientApi_Vulkan
GlfwClientApi_Vulkan,
};
struct ImGui_ImplGlfw_Data
@@ -152,6 +156,9 @@ struct ImGui_ImplGlfw_Data
bool InstalledCallbacks;
bool CallbacksChainForAllWindows;
bool WantUpdateMonitors;
#ifdef __EMSCRIPTEN__
const char* CanvasSelector;
#endif
// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
GLFWwindowfocusfun PrevUserCallbackWindowFocus;
@@ -565,6 +572,7 @@ void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows)
static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
//printf("GLFW_VERSION: %d.%d.%d (%d)", GLFW_VERSION_MAJOR, GLFW_VERSION_MINOR, GLFW_VERSION_REVISION, GLFW_VERSION_COMBINED);
@@ -577,7 +585,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
#ifndef __EMSCRIPTEN__
io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
#endif
#if GLFW_HAS_MOUSE_PASSTHROUGH || (GLFW_HAS_WINDOW_HOVERED && defined(_WIN32))
#if GLFW_HAS_MOUSE_PASSTHROUGH || GLFW_HAS_WINDOW_HOVERED
io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can call io.AddMouseViewportEvent() with correct data (optional)
#endif
@@ -644,9 +652,9 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
// Windows: register a WndProc hook so we can intercept some messages.
#ifdef _WIN32
bd->PrevWndProc = (WNDPROC)::GetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC);
bd->PrevWndProc = (WNDPROC)::GetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC);
IM_ASSERT(bd->PrevWndProc != nullptr);
::SetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
#endif
bd->ClientApi = client_api;
@@ -688,7 +696,7 @@ void ImGui_ImplGlfw_Shutdown()
// Windows: restore our WndProc hook
#ifdef _WIN32
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
::SetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)bd->PrevWndProc);
::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)bd->PrevWndProc);
bd->PrevWndProc = nullptr;
#endif
@@ -704,7 +712,6 @@ static void ImGui_ImplGlfw_UpdateMouseData()
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGuiID mouse_viewport_id = 0;
const ImVec2 mouse_pos_prev = io.MousePos;
for (int n = 0; n < platform_io.Viewports.Size; n++)
@@ -745,7 +752,8 @@ static void ImGui_ImplGlfw_UpdateMouseData()
// (Optional) When using multiple viewports: call io.AddMouseViewportEvent() with the viewport the OS mouse cursor is hovering.
// If ImGuiBackendFlags_HasMouseHoveredViewport is not set by the backend, Dear imGui will ignore this field and infer the information using its flawed heuristic.
// - [X] GLFW >= 3.3 backend ON WINDOWS ONLY does correctly ignore viewports with the _NoInputs flag.
// - [X] GLFW >= 3.3 backend ON WINDOWS ONLY does correctly ignore viewports with the _NoInputs flag (since we implement hit via our WndProc hook)
// On other platforms we rely on the library fallbacking to its own search when reporting a viewport with _NoInputs flag.
// - [!] GLFW <= 3.2 backend CANNOT correctly ignore viewports with the _NoInputs flag, and CANNOT reported Hovered Viewport because of mouse capture.
// Some backend are not able to handle that correctly. If a backend report an hovered viewport that has the _NoInputs flag (e.g. when dragging a window
// for docking, the viewport has the _NoInputs flag in order to allow us to find the viewport under), then Dear ImGui is forced to ignore the value reported
@@ -753,12 +761,12 @@ static void ImGui_ImplGlfw_UpdateMouseData()
// - [X] GLFW backend correctly reports this regardless of another viewport behind focused and dragged from (we need this to find a useful drag and drop target).
// FIXME: This is currently only correct on Win32. See what we do below with the WM_NCHITTEST, missing an equivalent for other systems.
// See https://github.com/glfw/glfw/issues/1236 if you want to help in making this a GLFW feature.
#if GLFW_HAS_MOUSE_PASSTHROUGH || (GLFW_HAS_WINDOW_HOVERED && defined(_WIN32))
const bool window_no_input = (viewport->Flags & ImGuiViewportFlags_NoInputs) != 0;
#if GLFW_HAS_MOUSE_PASSTHROUGH
const bool window_no_input = (viewport->Flags & ImGuiViewportFlags_NoInputs) != 0;
glfwSetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH, window_no_input);
#endif
if (glfwGetWindowAttrib(window, GLFW_HOVERED) && !window_no_input)
#if GLFW_HAS_MOUSE_PASSTHROUGH || GLFW_HAS_WINDOW_HOVERED
if (glfwGetWindowAttrib(window, GLFW_HOVERED))
mouse_viewport_id = viewport->ID;
#else
// We cannot use bd->MouseWindow maintained from CursorEnter/Leave callbacks, because it is locked to the window capturing mouse.
@@ -895,7 +903,7 @@ void ImGui_ImplGlfw_NewFrame()
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplGlfw_InitForXXX()?");
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplGlfw_InitForXXX()?");
// Setup display size (every frame to accommodate for window resizing)
int w, h;
@@ -923,6 +931,43 @@ void ImGui_ImplGlfw_NewFrame()
ImGui_ImplGlfw_UpdateGamepads();
}
#ifdef __EMSCRIPTEN__
static EM_BOOL ImGui_ImplGlfw_OnCanvasSizeChange(int event_type, const EmscriptenUiEvent* event, void* user_data)
{
ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data;
double canvas_width, canvas_height;
emscripten_get_element_css_size(bd->CanvasSelector, &canvas_width, &canvas_height);
glfwSetWindowSize(bd->Window, (int)canvas_width, (int)canvas_height);
return true;
}
static EM_BOOL ImGui_ImplEmscripten_FullscreenChangeCallback(int event_type, const EmscriptenFullscreenChangeEvent* event, void* user_data)
{
ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data;
double canvas_width, canvas_height;
emscripten_get_element_css_size(bd->CanvasSelector, &canvas_width, &canvas_height);
glfwSetWindowSize(bd->Window, (int)canvas_width, (int)canvas_height);
return true;
}
// 'canvas_selector' is a CSS selector. The event listener is applied to the first element that matches the query.
// STRING MUST PERSIST FOR THE APPLICATION DURATION. PLEASE USE A STRING LITERAL OR ENSURE POINTER WILL STAY VALID.
void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector)
{
IM_ASSERT(canvas_selector != nullptr);
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplGlfw_InitForXXX()?");
bd->CanvasSelector = canvas_selector;
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, bd, false, ImGui_ImplGlfw_OnCanvasSizeChange);
emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, bd, false, ImGui_ImplEmscripten_FullscreenChangeCallback);
// Change the size of the GLFW window according to the size of the canvas
ImGui_ImplGlfw_OnCanvasSizeChange(EMSCRIPTEN_EVENT_RESIZE, {}, bd);
}
#endif
//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
@@ -1076,8 +1121,8 @@ static void ImGui_ImplGlfw_ShowWindow(ImGuiViewport* viewport)
// GLFW hack: install hook for WM_NCHITTEST message handler
#if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED && defined(_WIN32)
::SetPropA(hwnd, "IMGUI_VIEWPORT", viewport);
vd->PrevWndProc = (WNDPROC)::GetWindowLongPtr(hwnd, GWLP_WNDPROC);
::SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
vd->PrevWndProc = (WNDPROC)::GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
::SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
#endif
#if !GLFW_HAS_FOCUS_ON_SHOW
@@ -1264,7 +1309,7 @@ static void ImGui_ImplGlfw_ShutdownPlatformInterface()
//-----------------------------------------------------------------------------
// WndProc hook (declared here because we will need access to ImGui_ImplGlfw_ViewportData)
// WndProc hook (declared here because we will need access to ImGui_ImplGlfw_ViewportData)
#ifdef _WIN32
static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo()
{
@@ -1311,7 +1356,7 @@ static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wPara
}
#endif
}
return ::CallWindowProc(prev_wndproc, hWnd, msg, wParam, lParam);
return ::CallWindowProcW(prev_wndproc, hWnd, msg, wParam, lParam);
}
#endif // #ifdef _WIN32

View File

@@ -8,11 +8,10 @@
// [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 will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [x] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// Issues:
// [ ] Platform: Multi-viewport support: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
// 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.
@@ -35,6 +34,11 @@ IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool ins
IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown();
IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
// Emscripten related initialization phase methods
#ifdef __EMSCRIPTEN__
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector);
#endif
// GLFW callbacks install
// - When calling Init with 'install_callbacks=true': ImGui_ImplGlfw_InstallCallbacks() is called. GLFW callbacks will be installed for you. They will chain-call user's previously installed callbacks, if any.
// - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call individual function yourself from your own GLFW callbacks.

View File

@@ -167,6 +167,7 @@ static ImGuiKey ImGui_ImplGLUT_KeyToImGuiKey(int key)
bool ImGui_ImplGLUT_Init()
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
#ifdef FREEGLUT
io.BackendPlatformName = "imgui_impl_glut (freeglut)";

View File

@@ -16,7 +16,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Metal: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-XX-XX: Metal: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2022-08-23: Metal: Update deprecated property 'sampleCount'->'rasterSampleCount'.
// 2022-07-05: Metal: Add dispatch synchronization.
// 2022-06-30: Metal: Use __bridge for ARC based systems.
@@ -87,7 +87,6 @@ struct ImGui_ImplMetal_Data
ImGui_ImplMetal_Data() { memset(this, 0, sizeof(*this)); }
};
static ImGui_ImplMetal_Data* ImGui_ImplMetal_CreateBackendData() { return IM_NEW(ImGui_ImplMetal_Data)(); }
static ImGui_ImplMetal_Data* ImGui_ImplMetal_GetBackendData() { return ImGui::GetCurrentContext() ? (ImGui_ImplMetal_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; }
static void ImGui_ImplMetal_DestroyBackendData(){ IM_DELETE(ImGui_ImplMetal_GetBackendData()); }
@@ -133,8 +132,11 @@ bool ImGui_ImplMetal_CreateDeviceObjects(MTL::Device* device)
bool ImGui_ImplMetal_Init(id<MTLDevice> device)
{
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_CreateBackendData();
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
ImGui_ImplMetal_Data* bd = IM_NEW(ImGui_ImplMetal_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_metal";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
@@ -166,7 +168,7 @@ void ImGui_ImplMetal_Shutdown()
void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor* renderPassDescriptor)
{
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
IM_ASSERT(bd->SharedMetalContext != nil && "No Metal context. Did you call ImGui_ImplMetal_Init() ?");
IM_ASSERT(bd != nil && "Context or backend not initialized! Did you call ImGui_ImplMetal_Init()?");
bd->SharedMetalContext.framebufferDescriptor = [[FramebufferDescriptor alloc] initWithRenderPassDescriptor:renderPassDescriptor];
if (bd->SharedMetalContext.depthStencilState == nil)

View File

@@ -23,9 +23,9 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2021-12-08: OpenGL: Fixed mishandling of the the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86.
// 2021-12-08: OpenGL: Fixed mishandling of the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODEL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications.
@@ -89,6 +89,7 @@ static void ImGui_ImplOpenGL2_ShutdownPlatformInterface();
bool ImGui_ImplOpenGL2_Init()
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
@@ -120,7 +121,7 @@ void ImGui_ImplOpenGL2_Shutdown()
void ImGui_ImplOpenGL2_NewFrame()
{
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplOpenGL2_Init()?");
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplOpenGL2_Init()?");
if (!bd->FontTexture)
ImGui_ImplOpenGL2_CreateDeviceObjects();

View File

@@ -23,8 +23,11 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2023-11-08: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" instead of "libGL.so.1", accomodating for NetBSD systems having only "libGL.so.3" available. (#6983)
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-05-07: OpenGL: Update loader for Linux to support EGL/GLVND. (#7562)
// 2024-04-16: OpenGL: Detect ES3 contexts on desktop based on version string, to e.g. avoid calling glPolygonMode() on them. (#7447)
// 2024-01-09: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" and variants, fixing regression on distros missing a symlink.
// 2023-11-08: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" instead of "libGL.so.1", accommodating for NetBSD systems having only "libGL.so.3" available. (#6983)
// 2023-10-05: OpenGL: Rename symbols in our internal loader so that LTO compilation with another copy of gl3w is possible. (#6875, #6668, #4445)
// 2023-06-20: OpenGL: Fixed erroneous use glGetIntegerv(GL_CONTEXT_PROFILE_MASK) on contexts lower than 3.2. (#6539, #6333)
// 2023-05-09: OpenGL: Support for glBindSampler() backup/restore on ES3. (#6375)
@@ -177,9 +180,21 @@
#define GL_VERTEX_ARRAY_BINDING GL_VERTEX_ARRAY_BINDING_OES
#endif
// Desktop GL 2.0+ has glPolygonMode() which GL ES and WebGL don't have.
#ifdef GL_POLYGON_MODE
#define IMGUI_IMPL_HAS_POLYGON_MODE
// Desktop GL 2.0+ has extension and glPolygonMode() which GL ES and WebGL don't have..
// A desktop ES context can technically compile fine with our loader, so we also perform a runtime checks
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3)
#define IMGUI_IMPL_OPENGL_HAS_EXTENSIONS // has glGetIntegerv(GL_NUM_EXTENSIONS)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE // may have glPolygonMode()
#endif
// Desktop GL 2.1+ and GL ES 3.0+ have glBindBuffer() with GL_PIXEL_UNPACK_BUFFER target.
#if !defined(IMGUI_IMPL_OPENGL_ES2)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK
#endif
// Desktop GL 3.1+ has GL_PRIMITIVE_RESTART state
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_1)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
#endif
// Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have.
@@ -192,16 +207,6 @@
#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
#endif
// Desktop GL 3.1+ has GL_PRIMITIVE_RESTART state
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_1)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
#endif
// Desktop GL use extension detection
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS
#endif
// [Debugging]
//#define IMGUI_IMPL_OPENGL_DEBUG
#ifdef IMGUI_IMPL_OPENGL_DEBUG
@@ -230,6 +235,7 @@ struct ImGui_ImplOpenGL3_Data
unsigned int VboHandle, ElementsHandle;
GLsizeiptr VertexBufferSize;
GLsizeiptr IndexBufferSize;
bool HasPolygonMode;
bool HasClipOrigin;
bool UseBufferSubData;
@@ -275,6 +281,7 @@ struct ImGui_ImplOpenGL3_VtxAttribState
bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Initialize our loader
@@ -298,16 +305,13 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
bd->GlProfileIsES2 = true;
#else
// Desktop or GLES 3
const char* gl_version_str = (const char*)glGetString(GL_VERSION);
GLint major = 0;
GLint minor = 0;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
if (major == 0 && minor == 0)
{
// Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
const char* gl_version = (const char*)glGetString(GL_VERSION);
sscanf(gl_version, "%d.%d", &major, &minor);
}
sscanf(gl_version_str, "%d.%d", &major, &minor); // Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
bd->GlVersion = (GLuint)(major * 100 + minor * 10);
#if defined(GL_CONTEXT_PROFILE_MASK)
if (bd->GlVersion >= 320)
@@ -317,6 +321,9 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
#if defined(IMGUI_IMPL_OPENGL_ES3)
bd->GlProfileIsES3 = true;
#else
if (strncmp(gl_version_str, "OpenGL ES 3", 11) == 0)
bd->GlProfileIsES3 = true;
#endif
bd->UseBufferSubData = false;
@@ -331,7 +338,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
#endif
#ifdef IMGUI_IMPL_OPENGL_DEBUG
printf("GlVersion = %d\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2 = %d, GlProfileIsES3 = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
printf("GlVersion = %d, \"%s\"\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2 = %d, GlProfileIsES3 = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, gl_version_str, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
#endif
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
@@ -364,8 +371,11 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
// Detect extensions we support
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
bd->HasPolygonMode = (!bd->GlProfileIsES2 && !bd->GlProfileIsES3);
#endif
bd->HasClipOrigin = (bd->GlVersion >= 450);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS
#ifdef IMGUI_IMPL_OPENGL_HAS_EXTENSIONS
GLint num_extensions = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
for (GLint i = 0; i < num_extensions; i++)
@@ -399,7 +409,7 @@ void ImGui_ImplOpenGL3_Shutdown()
void ImGui_ImplOpenGL3_NewFrame()
{
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplOpenGL3_Init()?");
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplOpenGL3_Init()?");
if (!bd->ShaderHandle)
ImGui_ImplOpenGL3_CreateDeviceObjects();
@@ -421,8 +431,9 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
if (bd->GlVersion >= 310)
glDisable(GL_PRIMITIVE_RESTART);
#endif
#ifdef IMGUI_IMPL_HAS_POLYGON_MODE
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
if (bd->HasPolygonMode)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
// Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
@@ -510,8 +521,8 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object);
#endif
#ifdef IMGUI_IMPL_HAS_POLYGON_MODE
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
GLint last_polygon_mode[2]; if (bd->HasPolygonMode) { glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); }
#endif
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
@@ -649,18 +660,10 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
if (bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); }
#endif
#ifdef IMGUI_IMPL_HAS_POLYGON_MODE
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
// Desktop OpenGL 3.0 and OpenGL 3.1 had separate polygon draw modes for front-facing and back-facing faces of polygons
if (bd->GlVersion <= 310 || bd->GlProfileIsCompat)
{
glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]);
glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]);
}
else
{
glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
}
#endif // IMGUI_IMPL_HAS_POLYGON_MODE
if (bd->HasPolygonMode) { if (bd->GlVersion <= 310 || bd->GlProfileIsCompat) { glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]); } else { glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); } }
#endif // IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
@@ -757,6 +760,10 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
GLint last_texture, last_array_buffer;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK
GLint last_pixel_unpack_buffer = 0;
if (bd->GlVersion >= 210) { glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &last_pixel_unpack_buffer); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); }
#endif
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
GLint last_vertex_array;
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
@@ -930,6 +937,9 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
// Restore modified GL state
glBindTexture(GL_TEXTURE_2D, last_texture);
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK
if (bd->GlVersion >= 210) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, last_pixel_unpack_buffer); }
#endif
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
glBindVertexArray(last_vertex_array);
#endif

View File

@@ -42,9 +42,9 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture();
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
// Specific OpenGL ES versions
//#define IMGUI_IMPL_OPENGL_ES2 // Auto-detected on Emscripten
//#define IMGUI_IMPL_OPENGL_ES3 // Auto-detected on iOS/Android
// Configuration flags to add in your imconfig file:
//#define IMGUI_IMPL_OPENGL_ES2 // Enable ES 2 (Auto-detected on Emscripten)
//#define IMGUI_IMPL_OPENGL_ES3 // Enable ES 3 (Auto-detected on iOS/Android)
// You can explicitly select GLES2 or GLES3 API by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line.
#if !defined(IMGUI_IMPL_OPENGL_ES2) \

View File

@@ -10,7 +10,7 @@
// THE REST OF YOUR APP SHOULD USE A DIFFERENT GL LOADER: ANY GL LOADER OF YOUR CHOICE.
//
// IF YOU GET BUILD ERRORS IN THIS FILE (commonly macro redefinitions or function redefinitions):
// IT LIKELY MEANS THAT YOU ARE BUILDING 'imgui_impl_opengl3.cpp' OR INCUDING 'imgui_impl_opengl3_loader.h'
// IT LIKELY MEANS THAT YOU ARE BUILDING 'imgui_impl_opengl3.cpp' OR INCLUDING 'imgui_impl_opengl3_loader.h'
// IN THE SAME COMPILATION UNIT AS ONE OF YOUR FILE WHICH IS USING A THIRD-PARTY OPENGL LOADER.
// (e.g. COULD HAPPEN IF YOU ARE DOING A UNITY/JUMBO BUILD, OR INCLUDING .CPP FILES FROM OTHERS)
// YOU SHOULD NOT BUILD BOTH IN THE SAME COMPILATION UNIT.
@@ -18,7 +18,7 @@
// WILL NOT BE USING OUR LOADER, AND INSTEAD EXPECT ANOTHER/YOUR LOADER TO BE AVAILABLE IN THE COMPILATION UNIT.
//
// Regenerate with:
// python gl3w_gen.py --output ../imgui/backends/imgui_impl_opengl3_loader.h --ref ../imgui/backends/imgui_impl_opengl3.cpp ./extra_symbols.txt
// python3 gl3w_gen.py --output ../imgui/backends/imgui_impl_opengl3_loader.h --ref ../imgui/backends/imgui_impl_opengl3.cpp ./extra_symbols.txt
//
// More info:
// https://github.com/dearimgui/gl3w_stripped
@@ -118,7 +118,7 @@ extern "C" {
** included as <GL/glcorearb.h>.
**
** glcorearb.h includes only APIs in the latest OpenGL core profile
** implementation together with APIs in newer ARB extensions which
** implementation together with APIs in newer ARB extensions which
** can be supported by the core profile. It does not, and never will
** include functionality removed from the core profile, such as
** fixed-function vertex and fragment processing.
@@ -346,6 +346,10 @@ GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean
GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
#endif
#endif /* GL_VERSION_2_0 */
#ifndef GL_VERSION_2_1
#define GL_PIXEL_UNPACK_BUFFER 0x88EC
#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
#endif /* GL_VERSION_2_1 */
#ifndef GL_VERSION_3_0
typedef khronos_uint16_t GLhalf;
#define GL_MAJOR_VERSION 0x821B
@@ -608,7 +612,7 @@ extern "C" {
#include <stdlib.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define GL3W_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#if defined(_WIN32)
#ifndef WIN32_LEAN_AND_MEAN
@@ -661,27 +665,123 @@ static GL3WglProc get_proc(const char *proc)
#else
#include <dlfcn.h>
static void *libgl;
static GL3WglProc (*glx_get_proc_address)(const GLubyte *);
static void* libgl; // OpenGL library
static void* libglx; // GLX library
static void* libegl; // EGL library
static GL3WGetProcAddressProc gl_get_proc_address;
static int open_libgl(void)
static void close_libgl(void)
{
if (libgl) {
dlclose(libgl);
libgl = NULL;
}
if (libegl) {
dlclose(libegl);
libegl = NULL;
}
if (libglx) {
dlclose(libglx);
libglx = NULL;
}
}
static int is_library_loaded(const char* name, void** lib)
{
*lib = dlopen(name, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
return *lib != NULL;
}
static int open_libs(void)
{
// On Linux we have two APIs to get process addresses: EGL and GLX.
// EGL is supported under both X11 and Wayland, whereas GLX is X11-specific.
libgl = NULL;
libegl = NULL;
libglx = NULL;
// First check what's already loaded, the windowing library might have
// already loaded either EGL or GLX and we want to use the same one.
if (is_library_loaded("libEGL.so.1", &libegl) ||
is_library_loaded("libGLX.so.0", &libglx)) {
libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL);
if (libgl)
return GL3W_OK;
else
close_libgl();
}
if (is_library_loaded("libGL.so", &libgl))
return GL3W_OK;
if (is_library_loaded("libGL.so.1", &libgl))
return GL3W_OK;
if (is_library_loaded("libGL.so.3", &libgl))
return GL3W_OK;
// Neither is already loaded, so we have to load one. Try EGL first
// because it is supported under both X11 and Wayland.
// Load OpenGL + EGL
libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL);
libegl = dlopen("libEGL.so.1", RTLD_LAZY | RTLD_LOCAL);
if (libgl && libegl)
return GL3W_OK;
else
close_libgl();
// Fall back to legacy libGL, which includes GLX
// While most systems use libGL.so.1, NetBSD seems to use that libGL.so.3. See https://github.com/ocornut/imgui/issues/6983
libgl = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL);
if (!libgl)
libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL);
if (!libgl)
libgl = dlopen("libGL.so.3", RTLD_LAZY | RTLD_LOCAL);
if (libgl)
return GL3W_OK;
return GL3W_ERROR_LIBRARY_OPEN;
}
static int open_libgl(void)
{
int res = open_libs();
if (res)
return res;
if (libegl)
*(void**)(&gl_get_proc_address) = dlsym(libegl, "eglGetProcAddress");
else if (libglx)
*(void**)(&gl_get_proc_address) = dlsym(libglx, "glXGetProcAddressARB");
else
*(void**)(&gl_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB");
if (!gl_get_proc_address) {
close_libgl();
return GL3W_ERROR_LIBRARY_OPEN;
*(void **)(&glx_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB");
}
return GL3W_OK;
}
static void close_libgl(void) { dlclose(libgl); }
static GL3WglProc get_proc(const char *proc)
static GL3WglProc get_proc(const char* proc)
{
GL3WglProc res;
res = glx_get_proc_address((const GLubyte *)proc);
GL3WglProc res = NULL;
// Before EGL version 1.5, eglGetProcAddress doesn't support querying core
// functions and may return a dummy function if we try, so try to load the
// function from the GL library directly first.
if (libegl)
*(void**)(&res) = dlsym(libgl, proc);
if (!res)
*(void **)(&res) = dlsym(libgl, proc);
res = gl_get_proc_address(proc);
if (!libegl && !res)
*(void**)(&res) = dlsym(libgl, proc);
return res;
}
#endif
@@ -800,7 +900,7 @@ GL3W_API union ImGL3WProcs imgl3wProcs;
static void load_procs(GL3WGetProcAddressProc proc)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(proc_names); i++)
for (i = 0; i < GL3W_ARRAY_SIZE(proc_names); i++)
imgl3wProcs.ptr[i] = proc(proc_names[i]);
}

View File

@@ -10,7 +10,10 @@
// [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: IME support.
// [X] Platform: Multi-viewport / platform windows.
// [x] Platform: Multi-viewport / platform windows.
// Issues:
// [ ] Platform: Multi-viewport: Window size not correctly reported when enabling io.ConfigViewportsNoDecoration
// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.

View File

@@ -10,7 +10,10 @@
// [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: IME support.
// [X] Platform: Multi-viewport / platform windows.
// [x] Platform: Multi-viewport / platform windows.
// Issues:
// [ ] Platform: Multi-viewport: Window size not correctly reported when enabling io.ConfigViewportsNoDecoration
// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
// 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.
@@ -30,7 +33,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-XX-XX: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F20 function keys. Stopped mapping F13 into PrintScreen.
// 2023-04-09: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_Pen.
// 2023-02-01: Fixed scroll wheel scaling for devices emitting events with hasPreciseScrollingDeltas==false (e.g. non-Apple mices).
@@ -87,7 +90,6 @@ struct ImGui_ImplOSX_Data
ImGui_ImplOSX_Data() { memset(this, 0, sizeof(*this)); }
};
static ImGui_ImplOSX_Data* ImGui_ImplOSX_CreateBackendData() { return IM_NEW(ImGui_ImplOSX_Data)(); }
static ImGui_ImplOSX_Data* ImGui_ImplOSX_GetBackendData() { return (ImGui_ImplOSX_Data*)ImGui::GetIO().BackendPlatformUserData; }
static void ImGui_ImplOSX_DestroyBackendData() { IM_DELETE(ImGui_ImplOSX_GetBackendData()); }
@@ -140,12 +142,28 @@ static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view);
- (void)updateImePosWithView:(NSView *)view
{
NSWindow *window = view.window;
NSWindow* window = view.window;
if (!window)
return;
NSRect contentRect = [window contentRectForFrameRect:window.frame];
NSRect rect = NSMakeRect(_posX, contentRect.size.height - _posY, 0, 0);
_imeRect = [window convertRectToScreen:rect];
ImGuiIO& io = ImGui::GetIO();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
NSRect frame = window.frame;
NSRect contentRect = window.contentLayoutRect;
if (window.styleMask & NSWindowStyleMaskFullSizeContentView) // No title bar windows should be considered.
contentRect = frame;
NSRect firstScreenFrame = NSScreen.screens[0].frame;
_imeRect = NSMakeRect(_posX, _posY, 0, 0);
_imeRect.origin.y = firstScreenFrame.size.height - _imeRect.size.height - _imeRect.origin.y; // Opposite of ConvertNSRect()
}
else
{
NSRect contentRect = [window contentRectForFrameRect:window.frame];
NSRect rect = NSMakeRect(_posX, contentRect.size.height - _posY, 0, 0);
_imeRect = [window convertRectToScreen:rect];
}
}
- (void)viewDidMoveToWindow
@@ -404,20 +422,23 @@ IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(void* _Nullable view) {
bool ImGui_ImplOSX_Init(NSView* view)
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_CreateBackendData();
io.BackendPlatformUserData = (void*)bd;
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
// Setup backend capabilities flags
ImGui_ImplOSX_Data* bd = IM_NEW(ImGui_ImplOSX_Data)();
io.BackendPlatformUserData = (void*)bd;
io.BackendPlatformName = "imgui_impl_osx";
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
//io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
//io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can call io.AddMouseViewportEvent() with correct data (optional)
io.BackendPlatformName = "imgui_impl_osx";
bd->Observer = [ImGuiObserver new];
bd->Window = view.window ?: NSApp.orderedWindows.firstObject;
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
main_viewport->PlatformHandle = main_viewport->PlatformHandleRaw = (__bridge_retained void*)bd->Window;
ImGui_ImplOSX_UpdateMonitors();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplOSX_InitPlatformInterface();
@@ -553,7 +574,6 @@ static void ImGui_ImplOSX_UpdateMouseCursor()
static void ImGui_ImplOSX_UpdateGamepads()
{
ImGuiIO& io = ImGui::GetIO();
memset(io.NavInputs, 0, sizeof(io.NavInputs));
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
return;
@@ -620,6 +640,7 @@ static void ImGui_ImplOSX_UpdateImePosWithView(NSView* view)
void ImGui_ImplOSX_NewFrame(NSView* view)
{
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplOSX_Init()?");
ImGuiIO& io = ImGui::GetIO();
// Setup display size
@@ -862,9 +883,11 @@ struct ImGuiViewportDataOSX
@end
static void ConvertNSRect(NSScreen* screen, NSRect* r)
static void ConvertNSRect(NSRect* r)
{
r->origin.y = screen.frame.size.height - r->origin.y - r->size.height;
NSRect firstScreenFrame = NSScreen.screens[0].frame;
IM_ASSERT(firstScreenFrame.origin.x == 0 && firstScreenFrame.origin.y == 0);
r->origin.y = firstScreenFrame.size.height - r->origin.y - r->size.height;
}
static void ImGui_ImplOSX_CreateWindow(ImGuiViewport* viewport)
@@ -875,7 +898,7 @@ static void ImGui_ImplOSX_CreateWindow(ImGuiViewport* viewport)
NSScreen* screen = bd->Window.screen;
NSRect rect = NSMakeRect(viewport->Pos.x, viewport->Pos.y, viewport->Size.x, viewport->Size.y);
ConvertNSRect(screen, &rect);
ConvertNSRect(&rect);
NSWindowStyleMask styleMask = 0;
if (viewport->Flags & ImGuiViewportFlags_NoDecoration)
@@ -945,11 +968,13 @@ static ImVec2 ImGui_ImplOSX_GetWindowPos(ImGuiViewport* viewport)
IM_ASSERT(data->Window != 0);
NSWindow* window = data->Window;
NSScreen* screen = window.screen;
NSSize size = screen.frame.size;
NSRect frame = window.frame;
NSRect rect = window.contentLayoutRect;
return ImVec2(frame.origin.x, size.height - frame.origin.y - rect.size.height);
NSRect contentRect = window.contentLayoutRect;
if (window.styleMask & NSWindowStyleMaskFullSizeContentView) // No title bar windows should be considered.
contentRect = frame;
NSRect firstScreenFrame = NSScreen.screens[0].frame;
return ImVec2(frame.origin.x, firstScreenFrame.size.height - frame.origin.y - contentRect.size.height);
}
static void ImGui_ImplOSX_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos)
@@ -961,7 +986,7 @@ static void ImGui_ImplOSX_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos)
NSSize size = window.frame.size;
NSRect r = NSMakeRect(pos.x, pos.y, size.width, size.height);
ConvertNSRect(window.screen, &r);
ConvertNSRect(&r);
[window setFrameOrigin:r.origin];
}
@@ -1042,10 +1067,15 @@ static void ImGui_ImplOSX_UpdateMonitors()
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Monitors.resize(0);
NSRect firstScreenFrame = NSScreen.screens[0].frame;
IM_ASSERT(firstScreenFrame.origin.x == 0 && firstScreenFrame.origin.y == 0);
for (NSScreen* screen in NSScreen.screens)
{
NSRect frame = screen.frame;
NSRect visibleFrame = screen.visibleFrame;
ConvertNSRect(&frame);
ConvertNSRect(&visibleFrame);
ImGuiPlatformMonitor imgui_monitor;
imgui_monitor.MainPos = ImVec2(frame.origin.x, frame.origin.y);
@@ -1062,7 +1092,6 @@ static void ImGui_ImplOSX_UpdateMonitors()
static void ImGui_ImplOSX_InitPlatformInterface()
{
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
ImGui_ImplOSX_UpdateMonitors();
// Register platform interface (will be coupled with a renderer interface)
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();

View File

@@ -10,8 +10,9 @@
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// Missing features:
// [ ] Platform: Multi-viewport + Minimized windows seems to break mouse wheel events (at least under Windows).
// Issues:
// [ ] Platform: Multi-viewport: Minimized windows seems to break mouse wheel events (at least under Windows).
// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
// [x] Platform: Basic IME support. App needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
@@ -24,7 +25,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-02-14: Inputs: Handle gamepad disconnection. Added ImGui_ImplSDL2_SetGamepadMode().
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys.
// 2023-04-06: Inputs: Avoid calling SDL_StartTextInput()/SDL_StopTextInput() as they don't only pertain to IME. It's unclear exactly what their relation is to IME. (#6306)
// 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen. (#2702)
@@ -116,19 +118,26 @@ static const Uint32 SDL_WINDOW_VULKAN = 0x10000000;
// SDL Data
struct ImGui_ImplSDL2_Data
{
SDL_Window* Window;
SDL_Renderer* Renderer;
Uint64 Time;
Uint32 MouseWindowID;
int MouseButtonsDown;
SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT];
SDL_Cursor* LastMouseCursor;
int PendingMouseLeaveFrame;
char* ClipboardTextData;
bool MouseCanUseGlobalState;
bool MouseCanReportHoveredViewport; // This is hard to use/unreliable on SDL so we'll set ImGuiBackendFlags_HasMouseHoveredViewport dynamically based on state.
bool UseVulkan;
bool WantUpdateMonitors;
SDL_Window* Window;
SDL_Renderer* Renderer;
Uint64 Time;
char* ClipboardTextData;
bool UseVulkan;
bool WantUpdateMonitors;
// Mouse handling
Uint32 MouseWindowID;
int MouseButtonsDown;
SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT];
SDL_Cursor* MouseLastCursor;
int MouseLastLeaveFrame;
bool MouseCanUseGlobalState;
bool MouseCanReportHoveredViewport; // This is hard to use/unreliable on SDL so we'll set ImGuiBackendFlags_HasMouseHoveredViewport dynamically based on state.
// Gamepad handling
ImVector<SDL_GameController*> Gamepads;
ImGui_ImplSDL2_GamepadMode GamepadMode;
bool WantUpdateGamepadsList;
ImGui_ImplSDL2_Data() { memset((void*)this, 0, sizeof(*this)); }
};
@@ -319,8 +328,9 @@ static void ImGui_ImplSDL2_UpdateKeyModifiers(SDL_Keymod sdl_key_mods)
// If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field.
bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDL2_Init()?");
ImGuiIO& io = ImGui::GetIO();
switch (event->type)
{
@@ -405,10 +415,10 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
if (window_event == SDL_WINDOWEVENT_ENTER)
{
bd->MouseWindowID = event->window.windowID;
bd->PendingMouseLeaveFrame = 0;
bd->MouseLastLeaveFrame = 0;
}
if (window_event == SDL_WINDOWEVENT_LEAVE)
bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1;
bd->MouseLastLeaveFrame = ImGui::GetFrameCount() + 1;
if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED)
io.AddFocusEvent(true);
else if (window_event == SDL_WINDOWEVENT_FOCUS_LOST)
@@ -426,6 +436,12 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
}
return true;
}
case SDL_CONTROLLERDEVICEADDED:
case SDL_CONTROLLERDEVICEREMOVED:
{
bd->WantUpdateGamepadsList = true;
return true;
}
}
return false;
}
@@ -433,6 +449,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void* sdl_gl_context)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
// Check and store if we are on a SDL backend that supports global mouse position
@@ -473,6 +490,10 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void
io.ClipboardUserData = nullptr;
io.SetPlatformImeDataFn = ImGui_ImplSDL2_SetPlatformImeData;
// Gamepad handling
bd->GamepadMode = ImGui_ImplSDL2_GamepadMode_AutoFirst;
bd->WantUpdateGamepadsList = true;
// Load mouse cursors
bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
@@ -569,6 +590,8 @@ bool ImGui_ImplSDL2_InitForOther(SDL_Window* window)
return ImGui_ImplSDL2_Init(window, nullptr, nullptr);
}
static void ImGui_ImplSDL2_CloseGamepads();
void ImGui_ImplSDL2_Shutdown()
{
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
@@ -581,7 +604,7 @@ void ImGui_ImplSDL2_Shutdown()
SDL_free(bd->ClipboardTextData);
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
SDL_FreeCursor(bd->MouseCursors[cursor_n]);
bd->LastMouseCursor = nullptr;
ImGui_ImplSDL2_CloseGamepads();
io.BackendPlatformName = nullptr;
io.BackendPlatformUserData = nullptr;
@@ -670,59 +693,118 @@ static void ImGui_ImplSDL2_UpdateMouseCursor()
{
// Show OS mouse cursor
SDL_Cursor* expected_cursor = bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow];
if (bd->LastMouseCursor != expected_cursor)
if (bd->MouseLastCursor != expected_cursor)
{
SDL_SetCursor(expected_cursor); // SDL function doesn't have an early out (see #6113)
bd->LastMouseCursor = expected_cursor;
bd->MouseLastCursor = expected_cursor;
}
SDL_ShowCursor(SDL_TRUE);
}
}
static void ImGui_ImplSDL2_CloseGamepads()
{
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
if (bd->GamepadMode != ImGui_ImplSDL2_GamepadMode_Manual)
for (SDL_GameController* gamepad : bd->Gamepads)
SDL_GameControllerClose(gamepad);
bd->Gamepads.resize(0);
}
void ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode mode, struct _SDL_GameController** manual_gamepads_array, int manual_gamepads_count)
{
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
ImGui_ImplSDL2_CloseGamepads();
if (mode == ImGui_ImplSDL2_GamepadMode_Manual)
{
IM_ASSERT(manual_gamepads_array != nullptr && manual_gamepads_count > 0);
for (int n = 0; n < manual_gamepads_count; n++)
bd->Gamepads.push_back(manual_gamepads_array[n]);
}
else
{
IM_ASSERT(manual_gamepads_array == nullptr && manual_gamepads_count <= 0);
bd->WantUpdateGamepadsList = true;
}
bd->GamepadMode = mode;
}
static void ImGui_ImplSDL2_UpdateGamepadButton(ImGui_ImplSDL2_Data* bd, ImGuiIO& io, ImGuiKey key, SDL_GameControllerButton button_no)
{
bool merged_value = false;
for (SDL_GameController* gamepad : bd->Gamepads)
merged_value |= SDL_GameControllerGetButton(gamepad, button_no) != 0;
io.AddKeyEvent(key, merged_value);
}
static inline float Saturate(float v) { return v < 0.0f ? 0.0f : v > 1.0f ? 1.0f : v; }
static void ImGui_ImplSDL2_UpdateGamepadAnalog(ImGui_ImplSDL2_Data* bd, ImGuiIO& io, ImGuiKey key, SDL_GameControllerAxis axis_no, float v0, float v1)
{
float merged_value = 0.0f;
for (SDL_GameController* gamepad : bd->Gamepads)
{
float vn = Saturate((float)(SDL_GameControllerGetAxis(gamepad, axis_no) - v0) / (float)(v1 - v0));
if (merged_value < vn)
merged_value = vn;
}
io.AddKeyAnalogEvent(key, merged_value > 0.1f, merged_value);
}
static void ImGui_ImplSDL2_UpdateGamepads()
{
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
ImGuiIO& io = ImGui::GetIO();
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
return;
// Get gamepad
// Update list of controller(s) to use
if (bd->WantUpdateGamepadsList && bd->GamepadMode != ImGui_ImplSDL2_GamepadMode_Manual)
{
ImGui_ImplSDL2_CloseGamepads();
int joystick_count = SDL_NumJoysticks();
for (int n = 0; n < joystick_count; n++)
if (SDL_IsGameController(n))
if (SDL_GameController* gamepad = SDL_GameControllerOpen(n))
{
bd->Gamepads.push_back(gamepad);
if (bd->GamepadMode == ImGui_ImplSDL2_GamepadMode_AutoFirst)
break;
}
bd->WantUpdateGamepadsList = false;
}
// FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
return;
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
SDL_GameController* game_controller = SDL_GameControllerOpen(0);
if (!game_controller)
if (bd->Gamepads.Size == 0)
return;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
// Update gamepad inputs
#define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V)
#define MAP_BUTTON(KEY_NO, BUTTON_NO) { io.AddKeyEvent(KEY_NO, SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0); }
#define MAP_ANALOG(KEY_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / (float)(V1 - V0); vn = IM_SATURATE(vn); io.AddKeyAnalogEvent(KEY_NO, vn > 0.1f, vn); }
const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value.
MAP_BUTTON(ImGuiKey_GamepadStart, SDL_CONTROLLER_BUTTON_START);
MAP_BUTTON(ImGuiKey_GamepadBack, SDL_CONTROLLER_BUTTON_BACK);
MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SDL_CONTROLLER_BUTTON_X); // Xbox X, PS Square
MAP_BUTTON(ImGuiKey_GamepadFaceRight, SDL_CONTROLLER_BUTTON_B); // Xbox B, PS Circle
MAP_BUTTON(ImGuiKey_GamepadFaceUp, SDL_CONTROLLER_BUTTON_Y); // Xbox Y, PS Triangle
MAP_BUTTON(ImGuiKey_GamepadFaceDown, SDL_CONTROLLER_BUTTON_A); // Xbox A, PS Cross
MAP_BUTTON(ImGuiKey_GamepadDpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
MAP_BUTTON(ImGuiKey_GamepadDpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
MAP_BUTTON(ImGuiKey_GamepadDpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP);
MAP_BUTTON(ImGuiKey_GamepadDpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
MAP_BUTTON(ImGuiKey_GamepadL1, SDL_CONTROLLER_BUTTON_LEFTSHOULDER);
MAP_BUTTON(ImGuiKey_GamepadR1, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
MAP_ANALOG(ImGuiKey_GamepadL2, SDL_CONTROLLER_AXIS_TRIGGERLEFT, 0.0f, 32767);
MAP_ANALOG(ImGuiKey_GamepadR2, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 0.0f, 32767);
MAP_BUTTON(ImGuiKey_GamepadL3, SDL_CONTROLLER_BUTTON_LEFTSTICK);
MAP_BUTTON(ImGuiKey_GamepadR3, SDL_CONTROLLER_BUTTON_RIGHTSTICK);
MAP_ANALOG(ImGuiKey_GamepadLStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadLStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadLStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadLStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadRStickLeft, SDL_CONTROLLER_AXIS_RIGHTX, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadRStickRight, SDL_CONTROLLER_AXIS_RIGHTX, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadRStickUp, SDL_CONTROLLER_AXIS_RIGHTY, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadRStickDown, SDL_CONTROLLER_AXIS_RIGHTY, +thumb_dead_zone, +32767);
#undef MAP_BUTTON
#undef MAP_ANALOG
const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value.
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadStart, SDL_CONTROLLER_BUTTON_START);
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadBack, SDL_CONTROLLER_BUTTON_BACK);
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceLeft, SDL_CONTROLLER_BUTTON_X); // Xbox X, PS Square
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceRight, SDL_CONTROLLER_BUTTON_B); // Xbox B, PS Circle
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceUp, SDL_CONTROLLER_BUTTON_Y); // Xbox Y, PS Triangle
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceDown, SDL_CONTROLLER_BUTTON_A); // Xbox A, PS Cross
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP);
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadL1, SDL_CONTROLLER_BUTTON_LEFTSHOULDER);
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadR1, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadL2, SDL_CONTROLLER_AXIS_TRIGGERLEFT, 0.0f, 32767);
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadR2, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 0.0f, 32767);
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadL3, SDL_CONTROLLER_BUTTON_LEFTSTICK);
ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadR3, SDL_CONTROLLER_BUTTON_RIGHTSTICK);
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768);
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767);
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32768);
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767);
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickLeft, SDL_CONTROLLER_AXIS_RIGHTX, -thumb_dead_zone, -32768);
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickRight, SDL_CONTROLLER_AXIS_RIGHTX, +thumb_dead_zone, +32767);
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickUp, SDL_CONTROLLER_AXIS_RIGHTY, -thumb_dead_zone, -32768);
ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickDown, SDL_CONTROLLER_AXIS_RIGHTY, +thumb_dead_zone, +32767);
}
// FIXME: Note that doesn't update with DPI/Scaling change only as SDL2 doesn't have an event for it (SDL3 has).
@@ -761,7 +843,7 @@ static void ImGui_ImplSDL2_UpdateMonitors()
void ImGui_ImplSDL2_NewFrame()
{
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplSDL2_Init()?");
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDL2_Init()?");
ImGuiIO& io = ImGui::GetIO();
// Setup display size (every frame to accommodate for window resizing)
@@ -791,10 +873,10 @@ void ImGui_ImplSDL2_NewFrame()
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f);
bd->Time = current_time;
if (bd->PendingMouseLeaveFrame && bd->PendingMouseLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0)
if (bd->MouseLastLeaveFrame && bd->MouseLastLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0)
{
bd->MouseWindowID = 0;
bd->PendingMouseLeaveFrame = 0;
bd->MouseLastLeaveFrame = 0;
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
}

View File

@@ -9,8 +9,9 @@
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// Missing features:
// [ ] Platform: Multi-viewport + Minimized windows seems to break mouse wheel events (at least under Windows).
// Issues:
// [ ] Platform: Multi-viewport: Minimized windows seems to break mouse wheel events (at least under Windows).
// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
// [x] Platform: Basic IME support. App needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
@@ -27,6 +28,7 @@
struct SDL_Window;
struct SDL_Renderer;
struct _SDL_GameController;
typedef union SDL_Event SDL_Event;
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context);
@@ -39,8 +41,9 @@ IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown();
IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame();
IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event);
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
static inline void ImGui_ImplSDL2_NewFrame(SDL_Window*) { ImGui_ImplSDL2_NewFrame(); } // 1.84: removed unnecessary parameter
#endif
// Gamepad selection automatically starts in AutoFirst mode, picking first available SDL_Gamepad. You may override this.
// When using manual mode, caller is responsible for opening/closing gamepad.
enum ImGui_ImplSDL2_GamepadMode { ImGui_ImplSDL2_GamepadMode_AutoFirst, ImGui_ImplSDL2_GamepadMode_AutoAll, ImGui_ImplSDL2_GamepadMode_Manual };
IMGUI_IMPL_API void ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode mode, struct _SDL_GameController** manual_gamepads_array = NULL, int manual_gamepads_count = -1);
#endif // #ifndef IMGUI_DISABLE

View File

@@ -10,9 +10,10 @@
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [x] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable' -> the OS animation effect when window gets created/destroyed is problematic. SDL2 backend doesn't have issue.
// Missing features:
// [ ] Platform: Multi-viewport + Minimized windows seems to break mouse wheel events (at least under Windows).
// [x] Platform: Basic IME support. Position somehow broken in SDL3 + app needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!.
// Issues:
// [ ] Platform: Multi-viewport: Minimized windows seems to break mouse wheel events (at least under Windows).
// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
// [ ] Platform: IME SUPPORT IS BROKEN IN SDL3 BECAUSE INPUTS GETS SENT TO BOTH APP AND IME + app needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!.
// 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.
@@ -24,7 +25,9 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-04-15: Inputs: Re-enable calling SDL_StartTextInput()/SDL_StopTextInput() as SDL3 no longer enables it by default and should play nicer with IME.
// 2024-02-13: Inputs: Fixed gamepad support. Handle gamepad disconnection. Added ImGui_ImplSDL3_SetGamepadMode().
// 2023-11-13: Updated for recent SDL3 API changes.
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys.
// 2023-05-04: Fixed build on Emscripten/iOS/Android. (#6391)
@@ -61,22 +64,37 @@
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0
#endif
// FIXME-LEGACY: remove when SDL 3.1.3 preview is released.
#ifndef SDLK_APOSTROPHE
#define SDLK_APOSTROPHE SDLK_QUOTE
#endif
#ifndef SDLK_GRAVE
#define SDLK_GRAVE SDLK_BACKQUOTE
#endif
// SDL Data
struct ImGui_ImplSDL3_Data
{
SDL_Window* Window;
SDL_Renderer* Renderer;
Uint64 Time;
Uint32 MouseWindowID;
int MouseButtonsDown;
SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT];
SDL_Cursor* LastMouseCursor;
int PendingMouseLeaveFrame;
char* ClipboardTextData;
bool MouseCanUseGlobalState;
bool MouseCanReportHoveredViewport; // This is hard to use/unreliable on SDL so we'll set ImGuiBackendFlags_HasMouseHoveredViewport dynamically based on state.
bool UseVulkan;
bool WantUpdateMonitors;
SDL_Window* Window;
SDL_Renderer* Renderer;
Uint64 Time;
char* ClipboardTextData;
bool UseVulkan;
bool WantUpdateMonitors;
// Mouse handling
Uint32 MouseWindowID;
int MouseButtonsDown;
SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT];
SDL_Cursor* MouseLastCursor;
int MousePendingLeaveFrame;
bool MouseCanUseGlobalState;
bool MouseCanReportHoveredViewport; // This is hard to use/unreliable on SDL so we'll set ImGuiBackendFlags_HasMouseHoveredViewport dynamically based on state.
// Gamepad handling
ImVector<SDL_Gamepad*> Gamepads;
ImGui_ImplSDL3_GamepadMode GamepadMode;
bool WantUpdateGamepadsList;
ImGui_ImplSDL3_Data() { memset((void*)this, 0, sizeof(*this)); }
};
@@ -120,6 +138,11 @@ static void ImGui_ImplSDL3_SetPlatformImeData(ImGuiViewport* viewport, ImGuiPlat
r.w = 1;
r.h = (int)data->InputLineHeight;
SDL_SetTextInputRect(&r);
SDL_StartTextInput();
}
else
{
SDL_StopTextInput();
}
}
@@ -142,7 +165,7 @@ static ImGuiKey ImGui_ImplSDL3_KeycodeToImGuiKey(int keycode)
case SDLK_SPACE: return ImGuiKey_Space;
case SDLK_RETURN: return ImGuiKey_Enter;
case SDLK_ESCAPE: return ImGuiKey_Escape;
case SDLK_QUOTE: return ImGuiKey_Apostrophe;
case SDLK_APOSTROPHE: return ImGuiKey_Apostrophe;
case SDLK_COMMA: return ImGuiKey_Comma;
case SDLK_MINUS: return ImGuiKey_Minus;
case SDLK_PERIOD: return ImGuiKey_Period;
@@ -152,7 +175,7 @@ static ImGuiKey ImGui_ImplSDL3_KeycodeToImGuiKey(int keycode)
case SDLK_LEFTBRACKET: return ImGuiKey_LeftBracket;
case SDLK_BACKSLASH: return ImGuiKey_Backslash;
case SDLK_RIGHTBRACKET: return ImGuiKey_RightBracket;
case SDLK_BACKQUOTE: return ImGuiKey_GraveAccent;
case SDLK_GRAVE: return ImGuiKey_GraveAccent;
case SDLK_CAPSLOCK: return ImGuiKey_CapsLock;
case SDLK_SCROLLLOCK: return ImGuiKey_ScrollLock;
case SDLK_NUMLOCKCLEAR: return ImGuiKey_NumLock;
@@ -266,8 +289,9 @@ static void ImGui_ImplSDL3_UpdateKeyModifiers(SDL_Keymod sdl_key_mods)
// If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field.
bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDL3_Init()?");
ImGuiIO& io = ImGui::GetIO();
switch (event->type)
{
@@ -339,7 +363,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
case SDL_EVENT_WINDOW_MOUSE_ENTER:
{
bd->MouseWindowID = event->window.windowID;
bd->PendingMouseLeaveFrame = 0;
bd->MousePendingLeaveFrame = 0;
return true;
}
// - In some cases, when detaching a window from main viewport SDL may send SDL_WINDOWEVENT_ENTER one frame too late,
@@ -348,7 +372,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
// FIXME: Unconfirmed whether this is still needed with SDL3.
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
{
bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1;
bd->MousePendingLeaveFrame = ImGui::GetFrameCount() + 1;
return true;
}
case SDL_EVENT_WINDOW_FOCUS_GAINED:
@@ -371,6 +395,12 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
return true;
}
return true;
case SDL_EVENT_GAMEPAD_ADDED:
case SDL_EVENT_GAMEPAD_REMOVED:
{
bd->WantUpdateGamepadsList = true;
return true;
}
}
return false;
}
@@ -380,15 +410,16 @@ static void ImGui_ImplSDL3_SetupPlatformHandles(ImGuiViewport* viewport, SDL_Win
viewport->PlatformHandle = window;
viewport->PlatformHandleRaw = nullptr;
#if defined(__WIN32__) && !defined(__WINRT__)
viewport->PlatformHandleRaw = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.win32.hwnd", NULL);
viewport->PlatformHandleRaw = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.win32.hwnd", nullptr);
#elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA)
viewport->PlatformHandleRaw = (void*)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.window", NULL);
viewport->PlatformHandleRaw = (void*)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.window", nullptr);
#endif
}
static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void* sdl_gl_context)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
IM_UNUSED(sdl_gl_context); // Unused in this branch
@@ -430,16 +461,20 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
io.ClipboardUserData = nullptr;
io.SetPlatformImeDataFn = ImGui_ImplSDL3_SetPlatformImeData;
// Gamepad handling
bd->GamepadMode = ImGui_ImplSDL3_GamepadMode_AutoFirst;
bd->WantUpdateGamepadsList = true;
// Load mouse cursors
bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_DEFAULT);
bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_TEXT);
bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_MOVE);
bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NS_RESIZE);
bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_EW_RESIZE);
bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NESW_RESIZE);
bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NWSE_RESIZE);
bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_POINTER);
bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NOT_ALLOWED);
// Set platform dependent data in viewport
// Our mouse update function expect PlatformHandle to be filled for the main viewport
@@ -504,6 +539,8 @@ bool ImGui_ImplSDL3_InitForOther(SDL_Window* window)
return ImGui_ImplSDL3_Init(window, nullptr, nullptr);
}
static void ImGui_ImplSDL3_CloseGamepads();
void ImGui_ImplSDL3_Shutdown()
{
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
@@ -516,7 +553,7 @@ void ImGui_ImplSDL3_Shutdown()
SDL_free(bd->ClipboardTextData);
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
SDL_DestroyCursor(bd->MouseCursors[cursor_n]);
bd->LastMouseCursor = nullptr;
ImGui_ImplSDL3_CloseGamepads();
io.BackendPlatformName = nullptr;
io.BackendPlatformUserData = nullptr;
@@ -605,59 +642,119 @@ static void ImGui_ImplSDL3_UpdateMouseCursor()
{
// Show OS mouse cursor
SDL_Cursor* expected_cursor = bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow];
if (bd->LastMouseCursor != expected_cursor)
if (bd->MouseLastCursor != expected_cursor)
{
SDL_SetCursor(expected_cursor); // SDL function doesn't have an early out (see #6113)
bd->LastMouseCursor = expected_cursor;
bd->MouseLastCursor = expected_cursor;
}
SDL_ShowCursor();
}
}
static void ImGui_ImplSDL3_CloseGamepads()
{
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
if (bd->GamepadMode != ImGui_ImplSDL3_GamepadMode_Manual)
for (SDL_Gamepad* gamepad : bd->Gamepads)
SDL_CloseGamepad(gamepad);
bd->Gamepads.resize(0);
}
void ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode mode, SDL_Gamepad** manual_gamepads_array, int manual_gamepads_count)
{
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
ImGui_ImplSDL3_CloseGamepads();
if (mode == ImGui_ImplSDL3_GamepadMode_Manual)
{
IM_ASSERT(manual_gamepads_array != nullptr && manual_gamepads_count > 0);
for (int n = 0; n < manual_gamepads_count; n++)
bd->Gamepads.push_back(manual_gamepads_array[n]);
}
else
{
IM_ASSERT(manual_gamepads_array == nullptr && manual_gamepads_count <= 0);
bd->WantUpdateGamepadsList = true;
}
bd->GamepadMode = mode;
}
static void ImGui_ImplSDL3_UpdateGamepadButton(ImGui_ImplSDL3_Data* bd, ImGuiIO& io, ImGuiKey key, SDL_GamepadButton button_no)
{
bool merged_value = false;
for (SDL_Gamepad* gamepad : bd->Gamepads)
merged_value |= SDL_GetGamepadButton(gamepad, button_no) != 0;
io.AddKeyEvent(key, merged_value);
}
static inline float Saturate(float v) { return v < 0.0f ? 0.0f : v > 1.0f ? 1.0f : v; }
static void ImGui_ImplSDL3_UpdateGamepadAnalog(ImGui_ImplSDL3_Data* bd, ImGuiIO& io, ImGuiKey key, SDL_GamepadAxis axis_no, float v0, float v1)
{
float merged_value = 0.0f;
for (SDL_Gamepad* gamepad : bd->Gamepads)
{
float vn = Saturate((float)(SDL_GetGamepadAxis(gamepad, axis_no) - v0) / (float)(v1 - v0));
if (merged_value < vn)
merged_value = vn;
}
io.AddKeyAnalogEvent(key, merged_value > 0.1f, merged_value);
}
static void ImGui_ImplSDL3_UpdateGamepads()
{
ImGuiIO& io = ImGui::GetIO();
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
return;
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
// Get gamepad
// Update list of gamepads to use
if (bd->WantUpdateGamepadsList && bd->GamepadMode != ImGui_ImplSDL3_GamepadMode_Manual)
{
ImGui_ImplSDL3_CloseGamepads();
int sdl_gamepads_count = 0;
SDL_JoystickID* sdl_gamepads = SDL_GetGamepads(&sdl_gamepads_count);
for (int n = 0; n < sdl_gamepads_count; n++)
if (SDL_Gamepad* gamepad = SDL_OpenGamepad(sdl_gamepads[n]))
{
bd->Gamepads.push_back(gamepad);
if (bd->GamepadMode == ImGui_ImplSDL3_GamepadMode_AutoFirst)
break;
}
SDL_free(sdl_gamepads);
bd->WantUpdateGamepadsList = false;
}
// FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
return;
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
SDL_Gamepad* gamepad = SDL_OpenGamepad(0);
if (!gamepad)
if (bd->Gamepads.Size == 0)
return;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
// Update gamepad inputs
#define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V)
#define MAP_BUTTON(KEY_NO, BUTTON_NO) { io.AddKeyEvent(KEY_NO, SDL_GetGamepadButton(gamepad, BUTTON_NO) != 0); }
#define MAP_ANALOG(KEY_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GetGamepadAxis(gamepad, AXIS_NO) - V0) / (float)(V1 - V0); vn = IM_SATURATE(vn); io.AddKeyAnalogEvent(KEY_NO, vn > 0.1f, vn); }
const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value.
MAP_BUTTON(ImGuiKey_GamepadStart, SDL_GAMEPAD_BUTTON_START);
MAP_BUTTON(ImGuiKey_GamepadBack, SDL_GAMEPAD_BUTTON_BACK);
MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SDL_GAMEPAD_BUTTON_WEST); // Xbox X, PS Square
MAP_BUTTON(ImGuiKey_GamepadFaceRight, SDL_GAMEPAD_BUTTON_EAST); // Xbox B, PS Circle
MAP_BUTTON(ImGuiKey_GamepadFaceUp, SDL_GAMEPAD_BUTTON_NORTH); // Xbox Y, PS Triangle
MAP_BUTTON(ImGuiKey_GamepadFaceDown, SDL_GAMEPAD_BUTTON_SOUTH); // Xbox A, PS Cross
MAP_BUTTON(ImGuiKey_GamepadDpadLeft, SDL_GAMEPAD_BUTTON_DPAD_LEFT);
MAP_BUTTON(ImGuiKey_GamepadDpadRight, SDL_GAMEPAD_BUTTON_DPAD_RIGHT);
MAP_BUTTON(ImGuiKey_GamepadDpadUp, SDL_GAMEPAD_BUTTON_DPAD_UP);
MAP_BUTTON(ImGuiKey_GamepadDpadDown, SDL_GAMEPAD_BUTTON_DPAD_DOWN);
MAP_BUTTON(ImGuiKey_GamepadL1, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER);
MAP_BUTTON(ImGuiKey_GamepadR1, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER);
MAP_ANALOG(ImGuiKey_GamepadL2, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0.0f, 32767);
MAP_ANALOG(ImGuiKey_GamepadR2, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0.0f, 32767);
MAP_BUTTON(ImGuiKey_GamepadL3, SDL_GAMEPAD_BUTTON_LEFT_STICK);
MAP_BUTTON(ImGuiKey_GamepadR3, SDL_GAMEPAD_BUTTON_RIGHT_STICK);
MAP_ANALOG(ImGuiKey_GamepadLStickLeft, SDL_GAMEPAD_AXIS_LEFTX, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadLStickRight, SDL_GAMEPAD_AXIS_LEFTX, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadLStickUp, SDL_GAMEPAD_AXIS_LEFTY, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadLStickDown, SDL_GAMEPAD_AXIS_LEFTY, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadRStickLeft, SDL_GAMEPAD_AXIS_RIGHTX, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadRStickRight, SDL_GAMEPAD_AXIS_RIGHTX, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadRStickUp, SDL_GAMEPAD_AXIS_RIGHTY, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadRStickDown, SDL_GAMEPAD_AXIS_RIGHTY, +thumb_dead_zone, +32767);
#undef MAP_BUTTON
#undef MAP_ANALOG
const int thumb_dead_zone = 8000; // SDL_gamepad.h suggests using this value.
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadStart, SDL_GAMEPAD_BUTTON_START);
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadBack, SDL_GAMEPAD_BUTTON_BACK);
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceLeft, SDL_GAMEPAD_BUTTON_WEST); // Xbox X, PS Square
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceRight, SDL_GAMEPAD_BUTTON_EAST); // Xbox B, PS Circle
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceUp, SDL_GAMEPAD_BUTTON_NORTH); // Xbox Y, PS Triangle
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceDown, SDL_GAMEPAD_BUTTON_SOUTH); // Xbox A, PS Cross
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadLeft, SDL_GAMEPAD_BUTTON_DPAD_LEFT);
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadRight, SDL_GAMEPAD_BUTTON_DPAD_RIGHT);
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadUp, SDL_GAMEPAD_BUTTON_DPAD_UP);
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadDown, SDL_GAMEPAD_BUTTON_DPAD_DOWN);
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadL1, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER);
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadR1, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER);
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadL2, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0.0f, 32767);
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadR2, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0.0f, 32767);
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadL3, SDL_GAMEPAD_BUTTON_LEFT_STICK);
ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadR3, SDL_GAMEPAD_BUTTON_RIGHT_STICK);
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickLeft, SDL_GAMEPAD_AXIS_LEFTX, -thumb_dead_zone, -32768);
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickRight, SDL_GAMEPAD_AXIS_LEFTX, +thumb_dead_zone, +32767);
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickUp, SDL_GAMEPAD_AXIS_LEFTY, -thumb_dead_zone, -32768);
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickDown, SDL_GAMEPAD_AXIS_LEFTY, +thumb_dead_zone, +32767);
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickLeft, SDL_GAMEPAD_AXIS_RIGHTX, -thumb_dead_zone, -32768);
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickRight, SDL_GAMEPAD_AXIS_RIGHTX, +thumb_dead_zone, +32767);
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickUp, SDL_GAMEPAD_AXIS_RIGHTY, -thumb_dead_zone, -32768);
ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickDown, SDL_GAMEPAD_AXIS_RIGHTY, +thumb_dead_zone, +32767);
}
static void ImGui_ImplSDL3_UpdateMonitors()
@@ -692,7 +789,7 @@ static void ImGui_ImplSDL3_UpdateMonitors()
void ImGui_ImplSDL3_NewFrame()
{
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplSDL3_Init()?");
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDL3_Init()?");
ImGuiIO& io = ImGui::GetIO();
// Setup display size (every frame to accommodate for window resizing)
@@ -719,10 +816,10 @@ void ImGui_ImplSDL3_NewFrame()
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f);
bd->Time = current_time;
if (bd->PendingMouseLeaveFrame && bd->PendingMouseLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0)
if (bd->MousePendingLeaveFrame && bd->MousePendingLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0)
{
bd->MouseWindowID = 0;
bd->PendingMouseLeaveFrame = 0;
bd->MousePendingLeaveFrame = 0;
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
}

View File

@@ -10,9 +10,11 @@
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [x] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable' -> the OS animation effect when window gets created/destroyed is problematic. SDL2 backend doesn't have issue.
// Missing features:
// [ ] Platform: Multi-viewport + Minimized windows seems to break mouse wheel events (at least under Windows).
// Issues:
// [ ] Platform: Multi-viewport: Minimized windows seems to break mouse wheel events (at least under Windows).
// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
// [x] Platform: Basic IME support. Position somehow broken in SDL3 + app needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!.
// [ ] Platform: IME SUPPORT IS BROKEN IN SDL3 BECAUSE INPUTS GETS SENT TO BOTH APP AND IME + app needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!.
// 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.
@@ -28,6 +30,7 @@
struct SDL_Window;
struct SDL_Renderer;
struct SDL_Gamepad;
typedef union SDL_Event SDL_Event;
IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForOpenGL(SDL_Window* window, void* sdl_gl_context);
@@ -40,4 +43,9 @@ IMGUI_IMPL_API void ImGui_ImplSDL3_Shutdown();
IMGUI_IMPL_API void ImGui_ImplSDL3_NewFrame();
IMGUI_IMPL_API bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event);
// Gamepad selection automatically starts in AutoFirst mode, picking first available SDL_Gamepad. You may override this.
// When using manual mode, caller is responsible for opening/closing gamepad.
enum ImGui_ImplSDL3_GamepadMode { ImGui_ImplSDL3_GamepadMode_AutoFirst, ImGui_ImplSDL3_GamepadMode_AutoAll, ImGui_ImplSDL3_GamepadMode_Manual };
IMGUI_IMPL_API void ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode mode, SDL_Gamepad** manual_gamepads_array = NULL, int manual_gamepads_count = -1);
#endif // #ifndef IMGUI_DISABLE

View File

@@ -22,6 +22,7 @@
// - Introduction, links and more at the top of imgui.cpp
// CHANGELOG
// 2024-05-14: *BREAKING CHANGE* ImGui_ImplSDLRenderer3_RenderDrawData() requires SDL_Renderer* passed as parameter.
// 2023-05-30: Renamed imgui_impl_sdlrenderer.h/.cpp to imgui_impl_sdlrenderer2.h/.cpp to accommodate for upcoming SDL3.
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2021-12-21: Update SDL_RenderGeometryRaw() format to work with SDL 2.0.19.
@@ -49,9 +50,9 @@
// SDL_Renderer data
struct ImGui_ImplSDLRenderer2_Data
{
SDL_Renderer* SDLRenderer;
SDL_Renderer* Renderer; // Main viewport's renderer
SDL_Texture* FontTexture;
ImGui_ImplSDLRenderer2_Data() { memset((void*)this, 0, sizeof(*this)); }
ImGui_ImplSDLRenderer2_Data() { memset((void*)this, 0, sizeof(*this)); }
};
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
@@ -65,6 +66,7 @@ static ImGui_ImplSDLRenderer2_Data* ImGui_ImplSDLRenderer2_GetBackendData()
bool ImGui_ImplSDLRenderer2_Init(SDL_Renderer* renderer)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
IM_ASSERT(renderer != nullptr && "SDL_Renderer not initialized!");
@@ -74,7 +76,7 @@ bool ImGui_ImplSDLRenderer2_Init(SDL_Renderer* renderer)
io.BackendRendererName = "imgui_impl_sdlrenderer2";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
bd->SDLRenderer = renderer;
bd->Renderer = renderer;
return true;
}
@@ -93,35 +95,31 @@ void ImGui_ImplSDLRenderer2_Shutdown()
IM_DELETE(bd);
}
static void ImGui_ImplSDLRenderer2_SetupRenderState()
static void ImGui_ImplSDLRenderer2_SetupRenderState(SDL_Renderer* renderer)
{
ImGui_ImplSDLRenderer2_Data* bd = ImGui_ImplSDLRenderer2_GetBackendData();
// Clear out any viewports and cliprect set by the user
// FIXME: Technically speaking there are lots of other things we could backup/setup/restore during our render process.
SDL_RenderSetViewport(bd->SDLRenderer, nullptr);
SDL_RenderSetClipRect(bd->SDLRenderer, nullptr);
SDL_RenderSetViewport(renderer, nullptr);
SDL_RenderSetClipRect(renderer, nullptr);
}
void ImGui_ImplSDLRenderer2_NewFrame()
{
ImGui_ImplSDLRenderer2_Data* bd = ImGui_ImplSDLRenderer2_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplSDLRenderer2_Init()?");
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDLRenderer2_Init()?");
if (!bd->FontTexture)
ImGui_ImplSDLRenderer2_CreateDeviceObjects();
}
void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data)
void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer)
{
ImGui_ImplSDLRenderer2_Data* bd = ImGui_ImplSDLRenderer2_GetBackendData();
// If there's a scale factor set by the user, use that instead
// If the user has specified a scale factor to SDL_Renderer already via SDL_RenderSetScale(), SDL will scale whatever we pass
// to SDL_RenderGeometryRaw() by that scale factor. In that case we don't want to be also scaling it ourselves here.
float rsx = 1.0f;
float rsy = 1.0f;
SDL_RenderGetScale(bd->SDLRenderer, &rsx, &rsy);
SDL_RenderGetScale(renderer, &rsx, &rsy);
ImVec2 render_scale;
render_scale.x = (rsx == 1.0f) ? draw_data->FramebufferScale.x : 1.0f;
render_scale.y = (rsy == 1.0f) ? draw_data->FramebufferScale.y : 1.0f;
@@ -140,16 +138,16 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data)
SDL_Rect ClipRect;
};
BackupSDLRendererState old = {};
old.ClipEnabled = SDL_RenderIsClipEnabled(bd->SDLRenderer) == SDL_TRUE;
SDL_RenderGetViewport(bd->SDLRenderer, &old.Viewport);
SDL_RenderGetClipRect(bd->SDLRenderer, &old.ClipRect);
old.ClipEnabled = SDL_RenderIsClipEnabled(renderer) == SDL_TRUE;
SDL_RenderGetViewport(renderer, &old.Viewport);
SDL_RenderGetClipRect(renderer, &old.ClipRect);
// Will project scissor/clipping rectangles into framebuffer space
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
ImVec2 clip_scale = render_scale;
// Render command lists
ImGui_ImplSDLRenderer2_SetupRenderState();
ImGui_ImplSDLRenderer2_SetupRenderState(renderer);
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
@@ -164,7 +162,7 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data)
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplSDLRenderer2_SetupRenderState();
ImGui_ImplSDLRenderer2_SetupRenderState(renderer);
else
pcmd->UserCallback(cmd_list, pcmd);
}
@@ -181,7 +179,7 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data)
continue;
SDL_Rect r = { (int)(clip_min.x), (int)(clip_min.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y) };
SDL_RenderSetClipRect(bd->SDLRenderer, &r);
SDL_RenderSetClipRect(renderer, &r);
const float* xy = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, pos));
const float* uv = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, uv));
@@ -193,7 +191,7 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data)
// Bind texture, Draw
SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID();
SDL_RenderGeometryRaw(bd->SDLRenderer, tex,
SDL_RenderGeometryRaw(renderer, tex,
xy, (int)sizeof(ImDrawVert),
color, (int)sizeof(ImDrawVert),
uv, (int)sizeof(ImDrawVert),
@@ -204,8 +202,8 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data)
}
// Restore modified SDL_Renderer state
SDL_RenderSetViewport(bd->SDLRenderer, &old.Viewport);
SDL_RenderSetClipRect(bd->SDLRenderer, old.ClipEnabled ? &old.ClipRect : nullptr);
SDL_RenderSetViewport(renderer, &old.Viewport);
SDL_RenderSetClipRect(renderer, old.ClipEnabled ? &old.ClipRect : nullptr);
}
// Called by Init/NewFrame/Shutdown
@@ -221,7 +219,7 @@ bool ImGui_ImplSDLRenderer2_CreateFontsTexture()
// Upload texture to graphics system
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
bd->FontTexture = SDL_CreateTexture(bd->SDLRenderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, width, height);
bd->FontTexture = SDL_CreateTexture(bd->Renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, width, height);
if (bd->FontTexture == nullptr)
{
SDL_Log("error creating texture");

View File

@@ -30,7 +30,7 @@ struct SDL_Renderer;
IMGUI_IMPL_API bool ImGui_ImplSDLRenderer2_Init(SDL_Renderer* renderer);
IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_Shutdown();
IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_NewFrame();
IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data);
IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer);
// Called by Init/NewFrame/Shutdown
IMGUI_IMPL_API bool ImGui_ImplSDLRenderer2_CreateFontsTexture();

View File

@@ -22,6 +22,8 @@
// - Introduction, links and more at the top of imgui.cpp
// CHANGELOG
// 2024-05-14: *BREAKING CHANGE* ImGui_ImplSDLRenderer3_RenderDrawData() requires SDL_Renderer* passed as parameter.
// 2024-02-12: Amend to query SDL_RenderViewportSet() and restore viewport accordingly.
// 2023-05-30: Initial version.
#include "imgui.h"
@@ -44,9 +46,9 @@
// SDL_Renderer data
struct ImGui_ImplSDLRenderer3_Data
{
SDL_Renderer* SDLRenderer;
SDL_Renderer* Renderer; // Main viewport's renderer
SDL_Texture* FontTexture;
ImGui_ImplSDLRenderer3_Data() { memset((void*)this, 0, sizeof(*this)); }
ImGui_ImplSDLRenderer3_Data() { memset((void*)this, 0, sizeof(*this)); }
};
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
@@ -60,6 +62,7 @@ static ImGui_ImplSDLRenderer3_Data* ImGui_ImplSDLRenderer3_GetBackendData()
bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
IM_ASSERT(renderer != nullptr && "SDL_Renderer not initialized!");
@@ -69,7 +72,7 @@ bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer)
io.BackendRendererName = "imgui_impl_sdlrenderer3";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
bd->SDLRenderer = renderer;
bd->Renderer = renderer;
return true;
}
@@ -88,35 +91,31 @@ void ImGui_ImplSDLRenderer3_Shutdown()
IM_DELETE(bd);
}
static void ImGui_ImplSDLRenderer3_SetupRenderState()
static void ImGui_ImplSDLRenderer3_SetupRenderState(SDL_Renderer* renderer)
{
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData();
// Clear out any viewports and cliprect set by the user
// FIXME: Technically speaking there are lots of other things we could backup/setup/restore during our render process.
SDL_SetRenderViewport(bd->SDLRenderer, nullptr);
SDL_SetRenderClipRect(bd->SDLRenderer, nullptr);
SDL_SetRenderViewport(renderer, nullptr);
SDL_SetRenderClipRect(renderer, nullptr);
}
void ImGui_ImplSDLRenderer3_NewFrame()
{
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplSDLRenderer3_Init()?");
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDLRenderer3_Init()?");
if (!bd->FontTexture)
ImGui_ImplSDLRenderer3_CreateDeviceObjects();
}
void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data)
void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer)
{
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData();
// If there's a scale factor set by the user, use that instead
// If the user has specified a scale factor to SDL_Renderer already via SDL_RenderSetScale(), SDL will scale whatever we pass
// to SDL_RenderGeometryRaw() by that scale factor. In that case we don't want to be also scaling it ourselves here.
float rsx = 1.0f;
float rsy = 1.0f;
SDL_GetRenderScale(bd->SDLRenderer, &rsx, &rsy);
SDL_GetRenderScale(renderer, &rsx, &rsy);
ImVec2 render_scale;
render_scale.x = (rsx == 1.0f) ? draw_data->FramebufferScale.x : 1.0f;
render_scale.y = (rsy == 1.0f) ? draw_data->FramebufferScale.y : 1.0f;
@@ -131,20 +130,22 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data)
struct BackupSDLRendererState
{
SDL_Rect Viewport;
bool ViewportEnabled;
bool ClipEnabled;
SDL_Rect ClipRect;
};
BackupSDLRendererState old = {};
old.ClipEnabled = SDL_RenderClipEnabled(bd->SDLRenderer) == SDL_TRUE;
SDL_GetRenderViewport(bd->SDLRenderer, &old.Viewport);
SDL_GetRenderClipRect(bd->SDLRenderer, &old.ClipRect);
old.ViewportEnabled = SDL_RenderViewportSet(renderer) == SDL_TRUE;
old.ClipEnabled = SDL_RenderClipEnabled(renderer) == SDL_TRUE;
SDL_GetRenderViewport(renderer, &old.Viewport);
SDL_GetRenderClipRect(renderer, &old.ClipRect);
// Will project scissor/clipping rectangles into framebuffer space
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
ImVec2 clip_scale = render_scale;
// Render command lists
ImGui_ImplSDLRenderer3_SetupRenderState();
ImGui_ImplSDLRenderer3_SetupRenderState(renderer);
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
@@ -159,7 +160,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data)
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplSDLRenderer3_SetupRenderState();
ImGui_ImplSDLRenderer3_SetupRenderState(renderer);
else
pcmd->UserCallback(cmd_list, pcmd);
}
@@ -176,19 +177,15 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data)
continue;
SDL_Rect r = { (int)(clip_min.x), (int)(clip_min.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y) };
SDL_SetRenderClipRect(bd->SDLRenderer, &r);
SDL_SetRenderClipRect(renderer, &r);
const float* xy = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, pos));
const float* uv = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, uv));
#if SDL_VERSION_ATLEAST(2,0,19)
const SDL_Color* color = (const SDL_Color*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, col)); // SDL 2.0.19+
#else
const int* color = (const int*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, col)); // SDL 2.0.17 and 2.0.18
#endif
// Bind texture, Draw
SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID();
SDL_RenderGeometryRaw(bd->SDLRenderer, tex,
SDL_RenderGeometryRaw(renderer, tex,
xy, (int)sizeof(ImDrawVert),
color, (int)sizeof(ImDrawVert),
uv, (int)sizeof(ImDrawVert),
@@ -199,8 +196,8 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data)
}
// Restore modified SDL_Renderer state
SDL_SetRenderViewport(bd->SDLRenderer, &old.Viewport);
SDL_SetRenderClipRect(bd->SDLRenderer, old.ClipEnabled ? &old.ClipRect : nullptr);
SDL_SetRenderViewport(renderer, old.ViewportEnabled ? &old.Viewport : nullptr);
SDL_SetRenderClipRect(renderer, old.ClipEnabled ? &old.ClipRect : nullptr);
}
// Called by Init/NewFrame/Shutdown
@@ -216,7 +213,7 @@ bool ImGui_ImplSDLRenderer3_CreateFontsTexture()
// Upload texture to graphics system
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
bd->FontTexture = SDL_CreateTexture(bd->SDLRenderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, width, height);
bd->FontTexture = SDL_CreateTexture(bd->Renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, width, height);
if (bd->FontTexture == nullptr)
{
SDL_Log("error creating texture");

View File

@@ -30,7 +30,7 @@ struct SDL_Renderer;
IMGUI_IMPL_API bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer);
IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_Shutdown();
IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_NewFrame();
IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data);
IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer);
// Called by Init/NewFrame/Shutdown
IMGUI_IMPL_API bool ImGui_ImplSDLRenderer3_CreateFontsTexture();

View File

@@ -34,16 +34,24 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-04-19: Vulkan: Added convenience support for Volk via IMGUI_IMPL_VULKAN_USE_VOLK define (you can also use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)
// 2024-02-14: *BREAKING CHANGE*: Moved RenderPass parameter from ImGui_ImplVulkan_Init() function to ImGui_ImplVulkan_InitInfo structure. Not required when using dynamic rendering.
// 2024-02-12: *BREAKING CHANGE*: Dynamic rendering now require filling PipelineRenderingCreateInfo structure.
// 2024-01-19: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236)
// 2024-01-11: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size (#3957). Fixed MinAllocationSize handing (#7189).
// 2024-01-03: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous "best practice" validation layer. (#7189, #4238)
// 2024-01-03: Vulkan: Stopped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT as we don't reset them.
// 2023-11-29: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs vkDestroyCommandPool(). (#7075)
// 2023-11-10: *BREAKING CHANGE*: Removed parameter from ImGui_ImplVulkan_CreateFontsTexture(): backend now creates its own command-buffer to upload fonts.
// *BREAKING CHANGE*: Removed ImGui_ImplVulkan_DestroyFontUploadObjects() which is now unecessary as we create and destroy those objects in the backend.
// *BREAKING CHANGE*: Removed ImGui_ImplVulkan_DestroyFontUploadObjects() which is now unnecessary as we create and destroy those objects in the backend.
// ImGui_ImplVulkan_CreateFontsTexture() is automatically called by NewFrame() the first time.
// You can call ImGui_ImplVulkan_CreateFontsTexture() again to recreate the font atlas texture.
// Added ImGui_ImplVulkan_DestroyFontsTexture() but you probably never need to call this.
// 2023-07-04: Vulkan: Added optional support for VK_KHR_dynamic_rendering. User needs to set init_info->UseDynamicRendering = true and init_info->ColorAttachmentFormat.
// 2023-01-02: Vulkan: Fixed sampler passed to ImGui_ImplVulkan_AddTexture() not being honored + removed a bunch of duplicate code.
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2022-10-04: Vulkan: Added experimental ImGui_ImplVulkan_RemoveTexture() for api symetry. (#914, #5738).
// 2022-10-04: Vulkan: Added experimental ImGui_ImplVulkan_RemoveTexture() for api symmetry. (#914, #5738).
// 2022-01-20: Vulkan: Added support for ImTextureID as VkDescriptorSet. User need to call ImGui_ImplVulkan_AddTexture(). Building for 32-bit targets requires '#define ImTextureID ImU64'. (#914).
// 2021-10-15: Vulkan: Call vkCmdSetScissor() at the end of render a full-viewport to reduce likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling vkCmdSetScissor() explicitly every frame.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
@@ -80,97 +88,37 @@
#ifndef IMGUI_DISABLE
#include "imgui_impl_vulkan.h"
#include <stdio.h>
#ifndef IM_MAX
#define IM_MAX(A, B) (((A) >= (B)) ? (A) : (B))
#endif
// Visual Studio warnings
#ifdef _MSC_VER
#pragma warning (disable: 4127) // condition expression is constant
#endif
// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplVulkan_RenderDrawData()
// [Please zero-clear before use!]
struct ImGui_ImplVulkanH_FrameRenderBuffers
{
VkDeviceMemory VertexBufferMemory;
VkDeviceMemory IndexBufferMemory;
VkDeviceSize VertexBufferSize;
VkDeviceSize IndexBufferSize;
VkBuffer VertexBuffer;
VkBuffer IndexBuffer;
};
// Each viewport will hold 1 ImGui_ImplVulkanH_WindowRenderBuffers
// [Please zero-clear before use!]
struct ImGui_ImplVulkanH_WindowRenderBuffers
{
uint32_t Index;
uint32_t Count;
ImGui_ImplVulkanH_FrameRenderBuffers* FrameRenderBuffers;
};
// For multi-viewport support:
// Helper structure we store in the void* RendererUserData field of each ImGuiViewport to easily retrieve our backend data.
struct ImGui_ImplVulkan_ViewportData
{
bool WindowOwned;
ImGui_ImplVulkanH_Window Window; // Used by secondary viewports only
ImGui_ImplVulkanH_WindowRenderBuffers RenderBuffers; // Used by all viewports
ImGui_ImplVulkan_ViewportData() { WindowOwned = false; memset(&RenderBuffers, 0, sizeof(RenderBuffers)); }
~ImGui_ImplVulkan_ViewportData() { }
};
// Vulkan data
struct ImGui_ImplVulkan_Data
{
ImGui_ImplVulkan_InitInfo VulkanInitInfo;
VkRenderPass RenderPass;
VkDeviceSize BufferMemoryAlignment;
VkPipelineCreateFlags PipelineCreateFlags;
VkDescriptorSetLayout DescriptorSetLayout;
VkPipelineLayout PipelineLayout;
VkPipeline Pipeline;
uint32_t Subpass;
VkShaderModule ShaderModuleVert;
VkShaderModule ShaderModuleFrag;
// Font data
VkSampler FontSampler;
VkDeviceMemory FontMemory;
VkImage FontImage;
VkImageView FontView;
VkDescriptorSet FontDescriptorSet;
VkCommandPool FontCommandPool;
VkCommandBuffer FontCommandBuffer;
// Render buffers for main window
ImGui_ImplVulkanH_WindowRenderBuffers MainWindowRenderBuffers;
ImGui_ImplVulkan_Data()
{
memset((void*)this, 0, sizeof(*this));
BufferMemoryAlignment = 256;
}
};
// Forward Declarations
struct ImGui_ImplVulkan_FrameRenderBuffers;
struct ImGui_ImplVulkan_WindowRenderBuffers;
bool ImGui_ImplVulkan_CreateDeviceObjects();
void ImGui_ImplVulkan_DestroyDeviceObjects();
void ImGui_ImplVulkan_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkan_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
void ImGui_ImplVulkan_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkan_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator);
void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator);
void ImGui_ImplVulkanH_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkanH_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkanH_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
void ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(VkDevice device, const VkAllocationCallbacks* allocator);
void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator);
// Vulkan prototypes for use with custom loaders
// (see description of IMGUI_IMPL_VULKAN_NO_PROTOTYPES in imgui_impl_vulkan.h
#ifdef VK_NO_PROTOTYPES
#if defined(VK_NO_PROTOTYPES) && !defined(VOLK_H_)
#define IMGUI_IMPL_VULKAN_USE_LOADER
static bool g_FunctionsLoaded = false;
#else
static bool g_FunctionsLoaded = true;
#endif
#ifdef VK_NO_PROTOTYPES
#ifdef IMGUI_IMPL_VULKAN_USE_LOADER
#define IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_MAP_MACRO) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateCommandBuffers) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateDescriptorSets) \
@@ -248,14 +196,79 @@ static bool g_FunctionsLoaded = true;
#define IMGUI_VULKAN_FUNC_DEF(func) static PFN_##func func;
IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_DEF)
#undef IMGUI_VULKAN_FUNC_DEF
#endif // VK_NO_PROTOTYPES
#endif // IMGUI_IMPL_VULKAN_USE_LOADER
#if defined(VK_VERSION_1_3) || defined(VK_KHR_dynamic_rendering)
#define IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
static PFN_vkCmdBeginRenderingKHR ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR;
static PFN_vkCmdEndRenderingKHR ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR;
#endif
// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplVulkan_RenderDrawData()
// [Please zero-clear before use!]
struct ImGui_ImplVulkan_FrameRenderBuffers
{
VkDeviceMemory VertexBufferMemory;
VkDeviceMemory IndexBufferMemory;
VkDeviceSize VertexBufferSize;
VkDeviceSize IndexBufferSize;
VkBuffer VertexBuffer;
VkBuffer IndexBuffer;
};
// Each viewport will hold 1 ImGui_ImplVulkanH_WindowRenderBuffers
// [Please zero-clear before use!]
struct ImGui_ImplVulkan_WindowRenderBuffers
{
uint32_t Index;
uint32_t Count;
ImGui_ImplVulkan_FrameRenderBuffers* FrameRenderBuffers;
};
// For multi-viewport support:
// Helper structure we store in the void* RendererUserData field of each ImGuiViewport to easily retrieve our backend data.
struct ImGui_ImplVulkan_ViewportData
{
ImGui_ImplVulkanH_Window Window; // Used by secondary viewports only
ImGui_ImplVulkan_WindowRenderBuffers RenderBuffers; // Used by all viewports
bool WindowOwned;
bool SwapChainNeedRebuild; // Flag when viewport swapchain resized in the middle of processing a frame
ImGui_ImplVulkan_ViewportData() { WindowOwned = SwapChainNeedRebuild = false; memset(&RenderBuffers, 0, sizeof(RenderBuffers)); }
~ImGui_ImplVulkan_ViewportData() { }
};
// Vulkan data
struct ImGui_ImplVulkan_Data
{
ImGui_ImplVulkan_InitInfo VulkanInitInfo;
VkDeviceSize BufferMemoryAlignment;
VkPipelineCreateFlags PipelineCreateFlags;
VkDescriptorSetLayout DescriptorSetLayout;
VkPipelineLayout PipelineLayout;
VkPipeline Pipeline; // pipeline for main render pass (created by app)
VkPipeline PipelineForViewports; // pipeline for secondary viewports (created by backend)
VkShaderModule ShaderModuleVert;
VkShaderModule ShaderModuleFrag;
// Font data
VkSampler FontSampler;
VkDeviceMemory FontMemory;
VkImage FontImage;
VkImageView FontView;
VkDescriptorSet FontDescriptorSet;
VkCommandPool FontCommandPool;
VkCommandBuffer FontCommandBuffer;
// Render buffers for main window
ImGui_ImplVulkan_WindowRenderBuffers MainWindowRenderBuffers;
ImGui_ImplVulkan_Data()
{
memset((void*)this, 0, sizeof(*this));
BufferMemoryAlignment = 256;
}
};
//-----------------------------------------------------------------------------
// SHADERS
//-----------------------------------------------------------------------------
@@ -264,7 +277,7 @@ static PFN_vkCmdEndRenderingKHR ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR;
static void ImGui_ImplVulkan_InitPlatformInterface();
static void ImGui_ImplVulkan_ShutdownPlatformInterface();
// glsl_shader.vert, compiled with:
// backends/vulkan/glsl_shader.vert, compiled with:
// # glslangValidator -V -x -o glsl_shader.vert.u32 glsl_shader.vert
/*
#version 450 core
@@ -328,7 +341,7 @@ static uint32_t __glsl_shader_vert_spv[] =
0x0000002d,0x0000002c,0x000100fd,0x00010038
};
// glsl_shader.frag, compiled with:
// backends/vulkan/glsl_shader.frag, compiled with:
// # glslangValidator -V -x -o glsl_shader.frag.u32 glsl_shader.frag
/*
#version 450 core
@@ -403,7 +416,13 @@ static void check_vk_result(VkResult err)
v->CheckVkResultFn(err);
}
static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& p_buffer_size, size_t new_size, VkBufferUsageFlagBits usage)
// Same as IM_MEMALIGN(). 'alignment' must be a power of two.
static inline VkDeviceSize AlignBufferSize(VkDeviceSize size, VkDeviceSize alignment)
{
return (size + alignment - 1) & ~(alignment - 1);
}
static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& buffer_size, size_t new_size, VkBufferUsageFlagBits usage)
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
@@ -413,10 +432,10 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory
if (buffer_memory != VK_NULL_HANDLE)
vkFreeMemory(v->Device, buffer_memory, v->Allocator);
VkDeviceSize vertex_buffer_size_aligned = ((new_size - 1) / bd->BufferMemoryAlignment + 1) * bd->BufferMemoryAlignment;
VkDeviceSize buffer_size_aligned = AlignBufferSize(IM_MAX(v->MinAllocationSize, new_size), bd->BufferMemoryAlignment);
VkBufferCreateInfo buffer_info = {};
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
buffer_info.size = vertex_buffer_size_aligned;
buffer_info.size = buffer_size_aligned;
buffer_info.usage = usage;
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &buffer);
@@ -434,10 +453,10 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory
err = vkBindBufferMemory(v->Device, buffer, buffer_memory, 0);
check_vk_result(err);
p_buffer_size = req.size;
buffer_size = buffer_size_aligned;
}
static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height)
static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkan_FrameRenderBuffers* rb, int fb_width, int fb_height)
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
@@ -498,23 +517,23 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
// Allocate array to store enough vertex/index buffers. Each unique viewport gets its own storage.
ImGui_ImplVulkan_ViewportData* viewport_renderer_data = (ImGui_ImplVulkan_ViewportData*)draw_data->OwnerViewport->RendererUserData;
IM_ASSERT(viewport_renderer_data != nullptr);
ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &viewport_renderer_data->RenderBuffers;
ImGui_ImplVulkan_WindowRenderBuffers* wrb = &viewport_renderer_data->RenderBuffers;
if (wrb->FrameRenderBuffers == nullptr)
{
wrb->Index = 0;
wrb->Count = v->ImageCount;
wrb->FrameRenderBuffers = (ImGui_ImplVulkanH_FrameRenderBuffers*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameRenderBuffers) * wrb->Count);
memset(wrb->FrameRenderBuffers, 0, sizeof(ImGui_ImplVulkanH_FrameRenderBuffers) * wrb->Count);
wrb->FrameRenderBuffers = (ImGui_ImplVulkan_FrameRenderBuffers*)IM_ALLOC(sizeof(ImGui_ImplVulkan_FrameRenderBuffers) * wrb->Count);
memset(wrb->FrameRenderBuffers, 0, sizeof(ImGui_ImplVulkan_FrameRenderBuffers) * wrb->Count);
}
IM_ASSERT(wrb->Count == v->ImageCount);
wrb->Index = (wrb->Index + 1) % wrb->Count;
ImGui_ImplVulkanH_FrameRenderBuffers* rb = &wrb->FrameRenderBuffers[wrb->Index];
ImGui_ImplVulkan_FrameRenderBuffers* rb = &wrb->FrameRenderBuffers[wrb->Index];
if (draw_data->TotalVtxCount > 0)
{
// Create or resize the vertex/index buffers
size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert);
size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx);
size_t vertex_size = AlignBufferSize(draw_data->TotalVtxCount * sizeof(ImDrawVert), bd->BufferMemoryAlignment);
size_t index_size = AlignBufferSize(draw_data->TotalIdxCount * sizeof(ImDrawIdx), bd->BufferMemoryAlignment);
if (rb->VertexBuffer == VK_NULL_HANDLE || rb->VertexBufferSize < vertex_size)
CreateOrResizeBuffer(rb->VertexBuffer, rb->VertexBufferMemory, rb->VertexBufferSize, vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
if (rb->IndexBuffer == VK_NULL_HANDLE || rb->IndexBufferSize < index_size)
@@ -523,9 +542,9 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
// Upload vertex/index data into a single contiguous GPU buffer
ImDrawVert* vtx_dst = nullptr;
ImDrawIdx* idx_dst = nullptr;
VkResult err = vkMapMemory(v->Device, rb->VertexBufferMemory, 0, rb->VertexBufferSize, 0, (void**)(&vtx_dst));
VkResult err = vkMapMemory(v->Device, rb->VertexBufferMemory, 0, vertex_size, 0, (void**)&vtx_dst);
check_vk_result(err);
err = vkMapMemory(v->Device, rb->IndexBufferMemory, 0, rb->IndexBufferSize, 0, (void**)(&idx_dst));
err = vkMapMemory(v->Device, rb->IndexBufferMemory, 0, index_size, 0, (void**)&idx_dst);
check_vk_result(err);
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
@@ -644,9 +663,9 @@ bool ImGui_ImplVulkan_CreateFontsTexture()
{
VkCommandPoolCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
info.flags = 0;
info.queueFamilyIndex = v->QueueFamily;
vkCreateCommandPool(v->Device, &info, nullptr, &bd->FontCommandPool);
vkCreateCommandPool(v->Device, &info, v->Allocator, &bd->FontCommandPool);
}
if (bd->FontCommandBuffer == VK_NULL_HANDLE)
{
@@ -696,7 +715,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture()
vkGetImageMemoryRequirements(v->Device, bd->FontImage, &req);
VkMemoryAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
alloc_info.allocationSize = req.size;
alloc_info.allocationSize = IM_MAX(v->MinAllocationSize, req.size);
alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits);
err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &bd->FontMemory);
check_vk_result(err);
@@ -737,7 +756,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture()
bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->BufferMemoryAlignment : req.alignment;
VkMemoryAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
alloc_info.allocationSize = req.size;
alloc_info.allocationSize = IM_MAX(v->MinAllocationSize, req.size);
alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);
err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &upload_buffer_memory);
check_vk_result(err);
@@ -811,7 +830,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture()
err = vkQueueSubmit(v->Queue, 1, &end_info, VK_NULL_HANDLE);
check_vk_result(err);
err = vkDeviceWaitIdle(v->Device);
err = vkQueueWaitIdle(v->Queue);
check_vk_result(err);
vkDestroyBuffer(v->Device, upload_buffer, v->Allocator);
@@ -965,13 +984,11 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC
info.subpass = subpass;
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
VkPipelineRenderingCreateInfoKHR pipelineRenderingCreateInfo = {};
pipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR;
pipelineRenderingCreateInfo.colorAttachmentCount = 1;
pipelineRenderingCreateInfo.pColorAttachmentFormats = &bd->VulkanInitInfo.ColorAttachmentFormat;
if (bd->VulkanInitInfo.UseDynamicRendering)
{
info.pNext = &pipelineRenderingCreateInfo;
IM_ASSERT(bd->VulkanInitInfo.PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR");
IM_ASSERT(bd->VulkanInitInfo.PipelineRenderingCreateInfo.pNext == nullptr && "PipelineRenderingCreateInfo pNext must be NULL");
info.pNext = &bd->VulkanInitInfo.PipelineRenderingCreateInfo;
info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr.
}
#endif
@@ -1036,7 +1053,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
check_vk_result(err);
}
ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, bd->RenderPass, v->MSAASamples, &bd->Pipeline, bd->Subpass);
ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, v->RenderPass, v->MSAASamples, &bd->Pipeline, v->Subpass);
return true;
}
@@ -1048,6 +1065,7 @@ void ImGui_ImplVulkan_DestroyDeviceObjects()
ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(v->Device, v->Allocator);
ImGui_ImplVulkan_DestroyFontsTexture();
if (bd->FontCommandBuffer) { vkFreeCommandBuffers(v->Device, bd->FontCommandPool, 1, &bd->FontCommandBuffer); bd->FontCommandBuffer = VK_NULL_HANDLE; }
if (bd->FontCommandPool) { vkDestroyCommandPool(v->Device, bd->FontCommandPool, v->Allocator); bd->FontCommandPool = VK_NULL_HANDLE; }
if (bd->ShaderModuleVert) { vkDestroyShaderModule(v->Device, bd->ShaderModuleVert, v->Allocator); bd->ShaderModuleVert = VK_NULL_HANDLE; }
if (bd->ShaderModuleFrag) { vkDestroyShaderModule(v->Device, bd->ShaderModuleFrag, v->Allocator); bd->ShaderModuleFrag = VK_NULL_HANDLE; }
@@ -1055,6 +1073,7 @@ void ImGui_ImplVulkan_DestroyDeviceObjects()
if (bd->DescriptorSetLayout) { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayout, v->Allocator); bd->DescriptorSetLayout = VK_NULL_HANDLE; }
if (bd->PipelineLayout) { vkDestroyPipelineLayout(v->Device, bd->PipelineLayout, v->Allocator); bd->PipelineLayout = VK_NULL_HANDLE; }
if (bd->Pipeline) { vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator); bd->Pipeline = VK_NULL_HANDLE; }
if (bd->PipelineForViewports) { vkDestroyPipeline(v->Device, bd->PipelineForViewports, v->Allocator); bd->PipelineForViewports = VK_NULL_HANDLE; }
}
bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data)
@@ -1062,8 +1081,8 @@ bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const ch
// Load function pointers
// You can use the default Vulkan loader using:
// ImGui_ImplVulkan_LoadFunctions([](const char* function_name, void*) { return vkGetInstanceProcAddr(your_vk_isntance, function_name); });
// But this would be equivalent to not setting VK_NO_PROTOTYPES.
#ifdef VK_NO_PROTOTYPES
// But this would be roughly equivalent to not setting VK_NO_PROTOTYPES.
#ifdef IMGUI_IMPL_VULKAN_USE_LOADER
#define IMGUI_VULKAN_FUNC_LOAD(func) \
func = reinterpret_cast<decltype(func)>(loader_func(#func, user_data)); \
if (func == nullptr) \
@@ -1085,14 +1104,14 @@ bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const ch
return true;
}
bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass)
bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)
{
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
if (info->UseDynamicRendering)
{
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
#ifndef VK_NO_PROTOTYPES
#ifndef IMGUI_IMPL_VULKAN_USE_LOADER
ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast<PFN_vkCmdBeginRenderingKHR>(vkGetInstanceProcAddr(info->Instance, "vkCmdBeginRenderingKHR"));
ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast<PFN_vkCmdEndRenderingKHR>(vkGetInstanceProcAddr(info->Instance, "vkCmdEndRenderingKHR"));
#endif
@@ -1104,6 +1123,7 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend
}
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
@@ -1121,11 +1141,9 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend
IM_ASSERT(info->MinImageCount >= 2);
IM_ASSERT(info->ImageCount >= info->MinImageCount);
if (info->UseDynamicRendering == false)
IM_ASSERT(render_pass != VK_NULL_HANDLE);
IM_ASSERT(info->RenderPass != VK_NULL_HANDLE);
bd->VulkanInitInfo = *info;
bd->RenderPass = render_pass;
bd->Subpass = info->Subpass;
ImGui_ImplVulkan_CreateDeviceObjects();
@@ -1166,7 +1184,7 @@ void ImGui_ImplVulkan_Shutdown()
void ImGui_ImplVulkan_NewFrame()
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplVulkan_Init()?");
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplVulkan_Init()?");
if (!bd->FontDescriptorSet)
ImGui_ImplVulkan_CreateFontsTexture();
@@ -1231,6 +1249,26 @@ void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set)
vkFreeDescriptorSets(v->Device, v->DescriptorPool, 1, &descriptor_set);
}
void ImGui_ImplVulkan_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkan_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator)
{
if (buffers->VertexBuffer) { vkDestroyBuffer(device, buffers->VertexBuffer, allocator); buffers->VertexBuffer = VK_NULL_HANDLE; }
if (buffers->VertexBufferMemory) { vkFreeMemory(device, buffers->VertexBufferMemory, allocator); buffers->VertexBufferMemory = VK_NULL_HANDLE; }
if (buffers->IndexBuffer) { vkDestroyBuffer(device, buffers->IndexBuffer, allocator); buffers->IndexBuffer = VK_NULL_HANDLE; }
if (buffers->IndexBufferMemory) { vkFreeMemory(device, buffers->IndexBufferMemory, allocator); buffers->IndexBufferMemory = VK_NULL_HANDLE; }
buffers->VertexBufferSize = 0;
buffers->IndexBufferSize = 0;
}
void ImGui_ImplVulkan_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkan_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator)
{
for (uint32_t n = 0; n < buffers->Count; n++)
ImGui_ImplVulkan_DestroyFrameRenderBuffers(device, &buffers->FrameRenderBuffers[n], allocator);
IM_FREE(buffers->FrameRenderBuffers);
buffers->FrameRenderBuffers = nullptr;
buffers->Index = 0;
buffers->Count = 0;
}
//-------------------------------------------------------------------------
// Internal / Miscellaneous Vulkan Helpers
// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own app.)
@@ -1318,19 +1356,17 @@ VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_d
void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator)
{
IM_ASSERT(physical_device != VK_NULL_HANDLE && device != VK_NULL_HANDLE);
(void)physical_device;
(void)allocator;
IM_UNUSED(physical_device);
// Create Command Buffers
VkResult err;
for (uint32_t i = 0; i < wd->ImageCount; i++)
{
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i];
ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[i];
{
VkCommandPoolCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
info.flags = 0;
info.queueFamilyIndex = queue_family;
err = vkCreateCommandPool(device, &info, allocator, &fd->CommandPool);
check_vk_result(err);
@@ -1351,6 +1387,11 @@ void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_devi
err = vkCreateFence(device, &info, allocator, &fd->Fence);
check_vk_result(err);
}
}
for (uint32_t i = 0; i < wd->SemaphoreCount; i++)
{
ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[i];
{
VkSemaphoreCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
@@ -1386,10 +1427,9 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
// We don't use ImGui_ImplVulkanH_DestroyWindow() because we want to preserve the old swapchain to create the new one.
// Destroy old Framebuffer
for (uint32_t i = 0; i < wd->ImageCount; i++)
{
ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator);
for (uint32_t i = 0; i < wd->SemaphoreCount; i++)
ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator);
}
IM_FREE(wd->Frames);
IM_FREE(wd->FrameSemaphores);
wd->Frames = nullptr;
@@ -1397,8 +1437,6 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
wd->ImageCount = 0;
if (wd->RenderPass)
vkDestroyRenderPass(device, wd->RenderPass, allocator);
if (wd->Pipeline)
vkDestroyPipeline(device, wd->Pipeline, allocator);
// If min image count was not specified, request different count of images dependent on selected present mode
if (min_image_count == 0)
@@ -1448,11 +1486,12 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers);
check_vk_result(err);
IM_ASSERT(wd->Frames == nullptr);
IM_ASSERT(wd->Frames == nullptr && wd->FrameSemaphores == nullptr);
wd->SemaphoreCount = wd->ImageCount + 1;
wd->Frames = (ImGui_ImplVulkanH_Frame*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_Frame) * wd->ImageCount);
wd->FrameSemaphores = (ImGui_ImplVulkanH_FrameSemaphores*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameSemaphores) * wd->ImageCount);
wd->FrameSemaphores = (ImGui_ImplVulkanH_FrameSemaphores*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameSemaphores) * wd->SemaphoreCount);
memset(wd->Frames, 0, sizeof(wd->Frames[0]) * wd->ImageCount);
memset(wd->FrameSemaphores, 0, sizeof(wd->FrameSemaphores[0]) * wd->ImageCount);
memset(wd->FrameSemaphores, 0, sizeof(wd->FrameSemaphores[0]) * wd->SemaphoreCount);
for (uint32_t i = 0; i < wd->ImageCount; i++)
wd->Frames[i].Backbuffer = backbuffers[i];
}
@@ -1498,7 +1537,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
// We do not create a pipeline by default as this is also used by examples' main.cpp,
// but secondary viewport in multi-viewport mode may want to create one with:
//ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline, bd->Subpass);
//ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline, v->Subpass);
}
// Create The Image Views
@@ -1560,15 +1599,13 @@ void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui
//vkQueueWaitIdle(bd->Queue);
for (uint32_t i = 0; i < wd->ImageCount; i++)
{
ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator);
for (uint32_t i = 0; i < wd->SemaphoreCount; i++)
ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator);
}
IM_FREE(wd->Frames);
IM_FREE(wd->FrameSemaphores);
wd->Frames = nullptr;
wd->FrameSemaphores = nullptr;
vkDestroyPipeline(device, wd->Pipeline, allocator);
vkDestroyRenderPass(device, wd->RenderPass, allocator);
vkDestroySwapchainKHR(device, wd->Swapchain, allocator);
vkDestroySurfaceKHR(instance, wd->Surface, allocator);
@@ -1596,32 +1633,12 @@ void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH
fsd->ImageAcquiredSemaphore = fsd->RenderCompleteSemaphore = VK_NULL_HANDLE;
}
void ImGui_ImplVulkanH_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkanH_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator)
{
if (buffers->VertexBuffer) { vkDestroyBuffer(device, buffers->VertexBuffer, allocator); buffers->VertexBuffer = VK_NULL_HANDLE; }
if (buffers->VertexBufferMemory) { vkFreeMemory(device, buffers->VertexBufferMemory, allocator); buffers->VertexBufferMemory = VK_NULL_HANDLE; }
if (buffers->IndexBuffer) { vkDestroyBuffer(device, buffers->IndexBuffer, allocator); buffers->IndexBuffer = VK_NULL_HANDLE; }
if (buffers->IndexBufferMemory) { vkFreeMemory(device, buffers->IndexBufferMemory, allocator); buffers->IndexBufferMemory = VK_NULL_HANDLE; }
buffers->VertexBufferSize = 0;
buffers->IndexBufferSize = 0;
}
void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkanH_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator)
{
for (uint32_t n = 0; n < buffers->Count; n++)
ImGui_ImplVulkanH_DestroyFrameRenderBuffers(device, &buffers->FrameRenderBuffers[n], allocator);
IM_FREE(buffers->FrameRenderBuffers);
buffers->FrameRenderBuffers = nullptr;
buffers->Index = 0;
buffers->Count = 0;
}
void ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(VkDevice device, const VkAllocationCallbacks* allocator)
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
for (int n = 0; n < platform_io.Viewports.Size; n++)
if (ImGui_ImplVulkan_ViewportData* vd = (ImGui_ImplVulkan_ViewportData*)platform_io.Viewports[n]->RendererUserData)
ImGui_ImplVulkanH_DestroyWindowRenderBuffers(device, &vd->RenderBuffers, allocator);
ImGui_ImplVulkan_DestroyWindowRenderBuffers(device, &vd->RenderBuffers, allocator);
}
//--------------------------------------------------------------------------------------------------------
@@ -1653,13 +1670,17 @@ static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport)
}
// Select Surface Format
const VkFormat requestSurfaceImageFormat[] = {
#if defined(IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING)
v->UseDynamicRendering && v->ColorAttachmentFormat ? v->ColorAttachmentFormat : VK_FORMAT_B8G8R8A8_UNORM,
ImVector<VkFormat> requestSurfaceImageFormats;
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
for (uint32_t n = 0; n < v->PipelineRenderingCreateInfo.colorAttachmentCount; n++)
requestSurfaceImageFormats.push_back(v->PipelineRenderingCreateInfo.pColorAttachmentFormats[n]);
#endif
VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
const VkFormat defaultFormats[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
for (VkFormat format : defaultFormats)
requestSurfaceImageFormats.push_back(format);
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(v->PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(v->PhysicalDevice, wd->Surface, requestSurfaceImageFormats.Data, (size_t)requestSurfaceImageFormats.Size, requestSurfaceColorSpace);
// Select Present Mode
// FIXME-VULKAN: Even thought mailbox seems to get us maximum framerate with a single window, it halves framerate with a second window etc. (w/ Nvidia and SDK 1.82.1)
@@ -1672,6 +1693,10 @@ static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport)
wd->UseDynamicRendering = v->UseDynamicRendering;
ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, wd, v->QueueFamily, v->Allocator, (int)viewport->Size.x, (int)viewport->Size.y, v->MinImageCount);
vd->WindowOwned = true;
// Create pipeline (shared by all secondary viewports)
if (bd->PipelineForViewports == VK_NULL_HANDLE)
ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &bd->PipelineForViewports, 0);
}
static void ImGui_ImplVulkan_DestroyWindow(ImGuiViewport* viewport)
@@ -1683,7 +1708,7 @@ static void ImGui_ImplVulkan_DestroyWindow(ImGuiViewport* viewport)
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
if (vd->WindowOwned)
ImGui_ImplVulkanH_DestroyWindow(v->Instance, v->Device, &vd->Window, v->Allocator);
ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &vd->RenderBuffers, v->Allocator);
ImGui_ImplVulkan_DestroyWindowRenderBuffers(v->Device, &vd->RenderBuffers, v->Allocator);
IM_DELETE(vd);
}
viewport->RendererUserData = nullptr;
@@ -1708,13 +1733,25 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*)
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
VkResult err;
if (vd->SwapChainNeedRebuild)
{
ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, wd, v->QueueFamily, v->Allocator, (int)viewport->Size.x, (int)viewport->Size.y, v->MinImageCount);
vd->SwapChainNeedRebuild = false;
}
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex];
ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[wd->SemaphoreIndex];
{
{
err = vkAcquireNextImageKHR(v->Device, wd->Swapchain, UINT64_MAX, fsd->ImageAcquiredSemaphore, VK_NULL_HANDLE, &wd->FrameIndex);
check_vk_result(err);
fd = &wd->Frames[wd->FrameIndex];
err = vkAcquireNextImageKHR(v->Device, wd->Swapchain, UINT64_MAX, fsd->ImageAcquiredSemaphore, VK_NULL_HANDLE, &wd->FrameIndex);
if (err == VK_ERROR_OUT_OF_DATE_KHR)
{
// Since we are not going to swap this frame anyway, it's ok that recreation happens on next frame.
vd->SwapChainNeedRebuild = true;
return;
}
check_vk_result(err);
fd = &wd->Frames[wd->FrameIndex];
}
for (;;)
{
@@ -1786,7 +1823,7 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*)
}
}
ImGui_ImplVulkan_RenderDrawData(viewport->DrawData, fd->CommandBuffer, wd->Pipeline);
ImGui_ImplVulkan_RenderDrawData(viewport->DrawData, fd->CommandBuffer, bd->PipelineForViewports);
{
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
@@ -1840,6 +1877,9 @@ static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport, void*)
ImGui_ImplVulkanH_Window* wd = &vd->Window;
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
if (vd->SwapChainNeedRebuild) // Frame data became invalid in the middle of rendering
return;
VkResult err;
uint32_t present_index = wd->FrameIndex;
@@ -1853,12 +1893,14 @@ static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport, void*)
info.pImageIndices = &present_index;
err = vkQueuePresentKHR(v->Queue, &info);
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, &vd->Window, v->QueueFamily, v->Allocator, (int)viewport->Size.x, (int)viewport->Size.y, v->MinImageCount);
else
check_vk_result(err);
{
vd->SwapChainNeedRebuild = true;
return;
}
check_vk_result(err);
wd->FrameIndex = (wd->FrameIndex + 1) % wd->ImageCount; // This is for the next vkWaitForFences()
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores
wd->FrameIndex = (wd->FrameIndex + 1) % wd->ImageCount; // This is for the next vkWaitForFences()
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores
}
void ImGui_ImplVulkan_InitPlatformInterface()

View File

@@ -43,13 +43,31 @@
// If you have no idea what this is, leave it alone!
//#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES
// Vulkan includes
// Convenience support for Volk
// (you can also technically use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)
//#define IMGUI_IMPL_VULKAN_USE_VOLK
#if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES) && !defined(VK_NO_PROTOTYPES)
#define VK_NO_PROTOTYPES
#endif
#if defined(VK_USE_PLATFORM_WIN32_KHR) && !defined(NOMINMAX)
#define NOMINMAX
#endif
// Vulkan includes
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
#include <Volk/volk.h>
#else
#include <vulkan/vulkan.h>
#endif
#if defined(VK_VERSION_1_3) || defined(VK_KHR_dynamic_rendering)
#define IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
#endif
// Initialization data, for ImGui_ImplVulkan_Init()
// - VkDescriptorPool should be created with VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
// and must contain a pool size large enough to hold an ImGui VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor.
// - When using dynamic rendering, set UseDynamicRendering=true and fill PipelineRenderingCreateInfo structure.
// [Please zero-clear before use!]
struct ImGui_ImplVulkan_InitInfo
{
@@ -58,24 +76,31 @@ struct ImGui_ImplVulkan_InitInfo
VkDevice Device;
uint32_t QueueFamily;
VkQueue Queue;
VkDescriptorPool DescriptorPool; // See requirements in note above
VkRenderPass RenderPass; // Ignored if using dynamic rendering
uint32_t MinImageCount; // >= 2
uint32_t ImageCount; // >= MinImageCount
VkSampleCountFlagBits MSAASamples; // 0 defaults to VK_SAMPLE_COUNT_1_BIT
// (Optional)
VkPipelineCache PipelineCache;
VkDescriptorPool DescriptorPool;
uint32_t Subpass;
uint32_t MinImageCount; // >= 2
uint32_t ImageCount; // >= MinImageCount
VkSampleCountFlagBits MSAASamples; // >= VK_SAMPLE_COUNT_1_BIT (0 -> default to VK_SAMPLE_COUNT_1_BIT)
// Dynamic Rendering (Optional)
bool UseDynamicRendering; // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3.
VkFormat ColorAttachmentFormat; // Required for dynamic rendering
// (Optional) Dynamic Rendering
// Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3.
bool UseDynamicRendering;
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo;
#endif
// Allocation, Debugging
// (Optional) Allocation, Debugging
const VkAllocationCallbacks* Allocator;
void (*CheckVkResultFn)(VkResult err);
VkDeviceSize MinAllocationSize; // Minimum allocation size. Set to 1024*1024 to satisfy zealous best practices validation layer and waste a little memory.
};
// Called by user code
IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass);
IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info);
IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown();
IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame();
IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE);
@@ -113,8 +138,8 @@ struct ImGui_ImplVulkanH_Frame;
struct ImGui_ImplVulkanH_Window;
// Helpers
IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wnd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wnd, const VkAllocationCallbacks* allocator);
IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator);
IMGUI_IMPL_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space);
IMGUI_IMPL_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count);
IMGUI_IMPL_API int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode);
@@ -149,12 +174,12 @@ struct ImGui_ImplVulkanH_Window
VkSurfaceFormatKHR SurfaceFormat;
VkPresentModeKHR PresentMode;
VkRenderPass RenderPass;
VkPipeline Pipeline; // The window pipeline may uses a different VkRenderPass than the one passed in ImGui_ImplVulkan_InitInfo
bool UseDynamicRendering;
bool ClearEnable;
VkClearValue ClearValue;
uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)
uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)
uint32_t SemaphoreCount; // Number of simultaneous in-flight frames + 1, to be able to use it in vkAcquireNextImageKHR
uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data)
ImGui_ImplVulkanH_Frame* Frames;
ImGui_ImplVulkanH_FrameSemaphores* FrameSemaphores;

View File

@@ -18,6 +18,10 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2024-01-22: Added configurable PipelineMultisampleState struct. (#7240)
// 2024-01-22: (Breaking) ImGui_ImplWGPU_Init() now takes a ImGui_ImplWGPU_InitInfo structure instead of variety of parameters, allowing for easier further changes.
// 2024-01-22: Fixed pipeline layout leak. (#7245)
// 2024-01-17: Explicitly fill all of WGPUDepthStencilState since standard removed defaults.
// 2023-07-13: Use WGPUShaderModuleWGSLDescriptor's code instead of source. use WGPUMipmapFilterMode_Linear instead of WGPUFilterMode_Linear. (#6602)
// 2023-04-11: Align buffer sizes. Use WGSL shaders instead of precompiled SPIR-V.
// 2023-04-11: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
@@ -74,16 +78,17 @@ struct Uniforms
struct ImGui_ImplWGPU_Data
{
WGPUDevice wgpuDevice = nullptr;
WGPUQueue defaultQueue = nullptr;
WGPUTextureFormat renderTargetFormat = WGPUTextureFormat_Undefined;
WGPUTextureFormat depthStencilFormat = WGPUTextureFormat_Undefined;
WGPURenderPipeline pipelineState = nullptr;
ImGui_ImplWGPU_InitInfo initInfo;
WGPUDevice wgpuDevice = nullptr;
WGPUQueue defaultQueue = nullptr;
WGPUTextureFormat renderTargetFormat = WGPUTextureFormat_Undefined;
WGPUTextureFormat depthStencilFormat = WGPUTextureFormat_Undefined;
WGPURenderPipeline pipelineState = nullptr;
RenderResources renderResources;
FrameResources* pFrameResources = nullptr;
unsigned int numFramesInFlight = 0;
unsigned int frameIndex = UINT_MAX;
RenderResources renderResources;
FrameResources* pFrameResources = nullptr;
unsigned int numFramesInFlight = 0;
unsigned int frameIndex = UINT_MAX;
};
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
@@ -181,6 +186,12 @@ static void SafeRelease(WGPUBuffer& res)
wgpuBufferRelease(res);
res = nullptr;
}
static void SafeRelease(WGPUPipelineLayout& res)
{
if (res)
wgpuPipelineLayoutRelease(res);
res = nullptr;
}
static void SafeRelease(WGPURenderPipeline& res)
{
if (res)
@@ -331,7 +342,9 @@ static void ImGui_ImplWGPU_SetupRenderState(ImDrawData* draw_data, WGPURenderPas
void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder)
{
// Avoid rendering when minimized
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdListsCount == 0)
return;
// FIXME: Assuming that this only gets called once per frame!
@@ -450,6 +463,12 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
// Clamp to viewport as wgpuRenderPassEncoderSetScissorRect() won't accept values that are off bounds
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
@@ -559,9 +578,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
graphics_pipeline_desc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined;
graphics_pipeline_desc.primitive.frontFace = WGPUFrontFace_CW;
graphics_pipeline_desc.primitive.cullMode = WGPUCullMode_None;
graphics_pipeline_desc.multisample.count = 1;
graphics_pipeline_desc.multisample.mask = UINT_MAX;
graphics_pipeline_desc.multisample.alphaToCoverageEnabled = false;
graphics_pipeline_desc.multisample = bd->initInfo.PipelineMultisampleState;
// Bind group layouts
WGPUBindGroupLayoutEntry common_bg_layout_entries[2] = {};
@@ -648,7 +665,13 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
depth_stencil_state.depthWriteEnabled = false;
depth_stencil_state.depthCompare = WGPUCompareFunction_Always;
depth_stencil_state.stencilFront.compare = WGPUCompareFunction_Always;
depth_stencil_state.stencilFront.failOp = WGPUStencilOperation_Keep;
depth_stencil_state.stencilFront.depthFailOp = WGPUStencilOperation_Keep;
depth_stencil_state.stencilFront.passOp = WGPUStencilOperation_Keep;
depth_stencil_state.stencilBack.compare = WGPUCompareFunction_Always;
depth_stencil_state.stencilBack.failOp = WGPUStencilOperation_Keep;
depth_stencil_state.stencilBack.depthFailOp = WGPUStencilOperation_Keep;
depth_stencil_state.stencilBack.passOp = WGPUStencilOperation_Keep;
// Configure disabled depth-stencil state
graphics_pipeline_desc.depthStencil = (bd->depthStencilFormat == WGPUTextureFormat_Undefined) ? nullptr : &depth_stencil_state;
@@ -678,6 +701,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
SafeRelease(vertex_shader_desc.module);
SafeRelease(pixel_shader_desc.module);
SafeRelease(graphics_pipeline_desc.layout);
SafeRelease(bg_layouts[0]);
return true;
@@ -699,9 +723,10 @@ void ImGui_ImplWGPU_InvalidateDeviceObjects()
SafeRelease(bd->pFrameResources[i]);
}
bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextureFormat rt_format, WGPUTextureFormat depth_format)
bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
@@ -710,11 +735,12 @@ bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextur
io.BackendRendererName = "imgui_impl_webgpu";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
bd->wgpuDevice = device;
bd->initInfo = *init_info;
bd->wgpuDevice = init_info->Device;
bd->defaultQueue = wgpuDeviceGetQueue(bd->wgpuDevice);
bd->renderTargetFormat = rt_format;
bd->depthStencilFormat = depth_format;
bd->numFramesInFlight = num_frames_in_flight;
bd->renderTargetFormat = init_info->RenderTargetFormat;
bd->depthStencilFormat = init_info->DepthStencilFormat;
bd->numFramesInFlight = init_info->NumFramesInFlight;
bd->frameIndex = UINT_MAX;
bd->renderResources.FontTexture = nullptr;
@@ -727,8 +753,8 @@ bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextur
bd->renderResources.ImageBindGroupLayout = nullptr;
// Create buffers with a default size (they will later be grown as needed)
bd->pFrameResources = new FrameResources[num_frames_in_flight];
for (int i = 0; i < num_frames_in_flight; i++)
bd->pFrameResources = new FrameResources[bd->numFramesInFlight];
for (unsigned int i = 0; i < bd->numFramesInFlight; i++)
{
FrameResources* fr = &bd->pFrameResources[i];
fr->IndexBuffer = nullptr;

View File

@@ -22,7 +22,24 @@
#include <webgpu/webgpu.h>
IMGUI_IMPL_API bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextureFormat rt_format, WGPUTextureFormat depth_format = WGPUTextureFormat_Undefined);
// Initialization data, for ImGui_ImplWGPU_Init()
struct ImGui_ImplWGPU_InitInfo
{
WGPUDevice Device;
int NumFramesInFlight = 3;
WGPUTextureFormat RenderTargetFormat = WGPUTextureFormat_Undefined;
WGPUTextureFormat DepthStencilFormat = WGPUTextureFormat_Undefined;
WGPUMultisampleState PipelineMultisampleState = {};
ImGui_ImplWGPU_InitInfo()
{
PipelineMultisampleState.count = 1;
PipelineMultisampleState.mask = UINT32_MAX;
PipelineMultisampleState.alphaToCoverageEnabled = false;
}
};
IMGUI_IMPL_API bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info);
IMGUI_IMPL_API void ImGui_ImplWGPU_Shutdown();
IMGUI_IMPL_API void ImGui_ImplWGPU_NewFrame();
IMGUI_IMPL_API void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder);

View File

@@ -17,30 +17,12 @@
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
#include "imgui.h"
#ifndef IMGUI_DISABLE
#include "imgui_impl_win32.h"
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <windowsx.h> // GET_X_LPARAM(), GET_Y_LPARAM()
#include <tchar.h>
#include <dwmapi.h>
// Configuration flags to add in your imconfig.h file:
// Configuration flags to add in your imconfig file:
//#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD // Disable gamepad support. This was meaningful before <1.81 but we now load XInput dynamically so the option is now less relevant.
// Using XInput for gamepad (will load DLL dynamically)
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
#include <xinput.h>
typedef DWORD (WINAPI *PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*);
typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
#endif
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys.
// 2023-09-25: Inputs: Synthesize key-down event on key-up for VK_SNAPSHOT / ImGuiKey_PrintScreen as Windows doesn't emit it (same behavior as GLFW/SDL).
// 2023-09-07: Inputs: Added support for keyboard codepage conversion for when application is compiled in MBCS mode and using a non-Unicode window.
@@ -93,8 +75,36 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
// 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging.
// 2016-11-12: Inputs: Only call Win32 ::SetCursor(nullptr) when io.MouseDrawCursor is set.
#include "imgui.h"
#ifndef IMGUI_DISABLE
#include "imgui_impl_win32.h"
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <windowsx.h> // GET_X_LPARAM(), GET_Y_LPARAM()
#include <tchar.h>
#include <dwmapi.h>
// Using XInput for gamepad (will load DLL dynamically)
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
#include <xinput.h>
typedef DWORD(WINAPI* PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*);
typedef DWORD(WINAPI* PFN_XInputGetState)(DWORD, XINPUT_STATE*);
#endif
// Clang/GCC warnings with -Weverything
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcast-function-type" // warning: cast between incompatible function types (for loader)
#endif
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-function-type" // warning: cast between incompatible function types (for loader)
#endif
// Forward Declarations
static void ImGui_ImplWin32_InitPlatformInterface(bool platformHasOwnDC);
static void ImGui_ImplWin32_InitPlatformInterface(bool platform_has_own_dc);
static void ImGui_ImplWin32_ShutdownPlatformInterface();
static void ImGui_ImplWin32_UpdateMonitors();
@@ -144,6 +154,7 @@ static void ImGui_ImplWin32_UpdateKeyboardCodePage()
static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
INT64 perf_frequency, perf_counter;
@@ -442,9 +453,9 @@ static void ImGui_ImplWin32_UpdateMonitors()
void ImGui_ImplWin32_NewFrame()
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplWin32_Init()?");
IM_ASSERT(bd != nullptr && "Context or backend not initialized? Did you call ImGui_ImplWin32_Init()?");
ImGuiIO& io = ImGui::GetIO();
// Setup display size (every frame to accommodate for window resizing)
RECT rect = { 0, 0, 0, 0 };
@@ -642,11 +653,12 @@ static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo()
IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (ImGui::GetCurrentContext() == nullptr)
return 0;
ImGuiIO& io = ImGui::GetIO();
// Most backends don't have silent checks like this one, but we need it because WndProc are called early in CreateWindow().
// We silently allow both context or just only backend data to be nullptr.
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
if (bd == nullptr)
return 0;
ImGuiIO& io = ImGui::GetIO();
switch (msg)
{
@@ -674,7 +686,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
::ScreenToClient(hwnd, &mouse_pos);
io.AddMouseSourceEvent(mouse_source);
io.AddMousePosEvent((float)mouse_pos.x, (float)mouse_pos.y);
break;
return 0;
}
case WM_MOUSELEAVE:
case WM_NCMOUSELEAVE:
@@ -687,7 +699,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
bd->MouseTrackedArea = 0;
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
}
break;
return 0;
}
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
@@ -1067,10 +1079,20 @@ static void ImGui_ImplWin32_ShowWindow(ImGuiViewport* viewport)
{
ImGui_ImplWin32_ViewportData* vd = (ImGui_ImplWin32_ViewportData*)viewport->PlatformUserData;
IM_ASSERT(vd->Hwnd != 0);
// ShowParent() also brings parent to front, which is not always desirable,
// so we temporarily disable parenting. (#7354)
if (vd->HwndParent != NULL)
::SetWindowLongPtr(vd->Hwnd, GWLP_HWNDPARENT, (LONG_PTR)nullptr);
if (viewport->Flags & ImGuiViewportFlags_NoFocusOnAppearing)
::ShowWindow(vd->Hwnd, SW_SHOWNA);
else
::ShowWindow(vd->Hwnd, SW_SHOW);
// Restore
if (vd->HwndParent != NULL)
::SetWindowLongPtr(vd->Hwnd, GWLP_HWNDPARENT, (LONG_PTR)vd->HwndParent);
}
static void ImGui_ImplWin32_UpdateWindow(ImGuiViewport* viewport)
@@ -1324,4 +1346,11 @@ static void ImGui_ImplWin32_ShutdownPlatformInterface()
//---------------------------------------------------------------------------------------------------------
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
#endif // #ifndef IMGUI_DISABLE

View File

@@ -79,14 +79,14 @@ List of Renderer Backends:
imgui_impl_sdlrenderer2.cpp ; SDL_Renderer (optional component of SDL2 available from SDL 2.0.18+)
imgui_impl_sdlrenderer3.cpp ; SDL_Renderer (optional component of SDL3 available from SDL 3.0.0+)
imgui_impl_vulkan.cpp ; Vulkan
imgui_impl_wgpu.cpp ; WebGPU
imgui_impl_wgpu.cpp ; WebGPU (web and desktop)
List of high-level Frameworks Backends (combining Platform + Renderer):
imgui_impl_allegro5.cpp
Emscripten is also supported!
The SDL+GL, GLFW+GL and SDL+WebGPU examples are all ready to build and run with Emscripten.
The SDL+GL, GLFW+GL and GLFW+WebGPU examples are all ready to build and run with Emscripten.
### Backends for third-party frameworks, graphics API or other languages

View File

@@ -35,11 +35,556 @@ 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.90.8 (Released 2024-06-06)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.90.8
Breaking changes:
- Reordered various ImGuiInputTextFlags values. This should NOT be breaking unless
you are using generated headers that have values not matching the main library.
- Removed ImGuiButtonFlags_MouseButtonDefault_ = ImGuiButtonFlags_MouseButtonLeft
from imgui.h, was mostly unused and misleading.
Other changes:
- Inputs: fixed IsMouseClicked(..., repeat=true); broken in 1.90.7 on 2024/05/22.
(due to an internal api parameter swap, repeat wouldn't be honored and
ownership would be accidentally checked even though this api is meant to not
check ownership). (#7657) [@korenkonder]
- Windows: fixed altering FramePadding mid-frame not correctly affecting logic
responsible for honoring io.ConfigWindowsMoveFromTitleBarOnly. (#7576, #899)
- Scrollbar: made scrolling logic more standard: clicking above or below the
grab scrolls by one page, holding mouse button repeats scrolling. (#7328, #150)
- Scrollbar: fixed miscalculation of vertical scrollbar visibility when required
solely by the presence of an horizontal scrollbar. (#1574)
- InputScalar, InputInt, InputFloat: added ImGuiInputTextFlags_ParseEmptyRefVal
to parse an empty field as zero-value. (#7305) [@supermerill, @ocornut]
- InputScalar, InputInt, InputFloat: added ImGuiInputTextFlags_DisplayEmptyRefVal
to display a zero-value as empty. (#7305) [@supermerill, @ocornut]
- Popups: fixed an issue preventing to close a popup opened over a modal by clicking
over void (it required clicking over the visible part of the modal). (#7654)
- Tables: fixed an issue where ideal size reported to parent container wouldn't
correctly take account of inner scrollbar, affecting potential auto-resize of
parent container. (#7651)
- Tables: fixed a bug where after disabling the ScrollY flag for a table,
previous scrollbar width would be accounted for. (#5920)
- Combo: simplified Combo() API uses a list clipper (due to its api it wasn't
previously trivial before we added clipper.IncludeItemByIndex() function).
- Disabled: nested tooltips or other non-child window within a BeginDisabled()
block disable the disabled state. (#211, #7640)
- Misc: made ImGuiDir and ImGuiSortDirection stronger-typed enums.
- Backends: SDL3: Update for SDL_SYSTEM_CURSOR_xxx api renames. (#7653)
-----------------------------------------------------------------------
VERSION 1.90.7 (Released 2024-05-27)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.90.7
Breaking changes:
- Inputs: on macOS X, Cmd and Ctrl keys are now automatically swapped by io.AddKeyEvent(),
as this naturally align with how macOS X uses those keys. (#2343, #4084, #5923, #456)
- Effectively it means that e.g. ImGuiMod_Ctrl | ImGuiKey_C is a valid idiomatic shortcut
for both Windows and Mac style users.
- It shouldn't really affect your code unless you had explicit/custom shortcut swapping in
place for macOS X apps in your input logic.
- Removed ImGuiMod_Shortcut which was previously dynamically remapping to Ctrl or Cmd/Super.
It is now unnecessary to specific cross-platform idiomatic shortcuts.
Kept symbols redirecting ImGuiMod_Shortcut to ImGuiMod_Ctrl (will obsolete).
- Commented out obsolete symbols renamed in 1.88 (May 2022):
CaptureKeyboardFromApp() -> SetNextFrameWantCaptureKeyboard()
CaptureMouseFromApp() -> SetNextFrameWantCaptureMouse()
- Backends: SDL_Renderer2/SDL_Renderer3: ImGui_ImplSDLRenderer2_RenderDrawData() and
ImGui_ImplSDLRenderer3_RenderDrawData() now takes a SDL_Renderer* parameter. This was previously
overlooked from the API but it will allow eventual support for multi-viewports.
Other changes:
- Windows: BeginChild(): fixed visibility of fully clipped child windows and tables to Test Engine.
- Windows: BeginChild(): fixed auto-fit calculation when using either (not both) ResizeX/ResizeY
and double-clicking on a border. Calculation incorrectly didn't always account for scrollbar as
it assumed the other axis would also be auto-fit. (#1710)
- Inputs: added shortcut and routing system in public API. (#456, #2637) [BETA]
- The general idea is that several callers may register interest in a shortcut, and only one owner gets it.
- in Parent: call Shortcut(Ctrl+S) // When Parent is focused, Parent gets the shortcut.
- in Child1: call Shortcut(Ctrl+S) // When Child1 is focused, Child1 gets the shortcut (Child1 overrides Parent shortcuts)
- in Child2: no call // When Child2 is focused, Parent gets the shortcut.
The whole system is order independent, so if Child1 makes its calls before Parent, results will be identical.
This is an important property as it facilitate working with foreign code or larger codebase.
- Added Shortcut() function:
e.g. Using ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_C); with default policy:
- checks that CTRL+C is pressed,
- and that current window is in focus stack,
- and that no other requests for CTRL+C have been made from higher priority locations
(e.g. deeper in the window/item stack).
- Added SetNextItemShortcut() to set a shortcut to locally or remotely press or activate
an item (depending on specified routing policy: using ImGuiInputFlags_RouteGlobal the item
shortcut may be executed even if its window is not in focus stack).
Items like buttons are not fully activated, in the sense that they get pressed but another
active item, e.g. InputText() won't be deactivated.
- Added routing policies for Shortcut(), SetNextItemShortcut(): (#456, #2637)
- ImGuiInputFlags_RouteFocused: focus stack route (default)
- ImGuiInputFlags_RouteActive: only route to active item
- ImGuiInputFlags_RouteGlobal: route globally, unless a focus route claim shame shortcut.
- ImGuiInputFlags_RouteAlways: no routing submission, no routing check.
- Added other shortcut/routing options: (#456, #2637)
- ImGuiInputFlags_Repeat: for use by Shortcut() and by upcoming rework of various
input functions (which are still internal for now).
- ImGuiInputFlags_Tooltip: for SetNextItemShortcut() to show a tooltip when hovering item.
- ImGuiInputFlags_RouteOverFocused: global route takes priority over focus route.
- ImGuiInputFlags_RouteOverActive: global route takes priority over active item.
- ImGuiInputFlags_RouteUnlessBgFocused: global route disabled if no imgui window focused.
- ImGuiInputFlags_RouteFromRootWindow: route evaluated from the point of view of root window rather than current window.
- Inputs: (OSX) Fixes variety of code which inconsistently required using Ctrl instead of Cmd.
- e.g. Drags/Sliders now use Cmd+Click to input a value. (#4084)
- Some shortcuts still uses Ctrl on Mac: e.g. Ctrl+Tab to switch windows. (#4828)
- Inputs: (OSX) Ctrl+Left Click alias as a Right click. (#2343) [@haldean, @ocornut]
- Inputs: Fixed ImGui::GetKeyName(ImGuiKey_None) from returning "N/A" or "None" depending
on value of IMGUI_DISABLE_OBSOLETE_KEYIO. It always returns "None".
- Nav: fixed holding Ctrl or gamepad L1 from not slowing down keyboard/gamepad tweak speed.
Broken during a refactor refactor for 1.89. Holding Shift/R1 to speed up wasn't broken.
- Tables: fixed cell background of fully clipped row overlapping with header. (#7575, #7041) [@prabuinet]
- Demo: Added "Inputs & Focus -> Shortcuts" section. (#456, #2637)
- Demo: Documents: Added shortcuts and renaming tabs/documents. (#7233)
- Examples: Win32+DX9,DX10,DX11,DX12: rework main loop to handle minimization and screen
locking without burning resources by running unthrottled code. (#2496, #3907, #6308, #7615)
- Backends: all backends + demo now call IMGUI_CHECKVERSION() to verify ABI compatibility between caller
code and compiled version of Dear ImGui. If you get an assert it most likely mean you have a build issue,
read comments near the assert. (#7568)
- Backends: Win32: undo an assert introduced in 1.90.6 which didn't allow WndProc
handler to be called before backend initialization. Because of how ::CreateWindow()
calls in WndProc this is facilitating. (#6275) [@MennoVink]
- Backends, Examples: SDL3: updates for latest SDL3 API changes. (#7580) [@kuvaus, @ocornut]
Breaking changes IF you were using imgui_internal.h versions of Shortcut() or owner-aware
versions of IsKeyPressed(), IsKeyChordPressed(), IsMouseClicked() prior to this version:
- Inputs (Internals): Renamed ImGuiKeyOwner_None to ImGuiKeyOwner_NoOwner, to make use more
explicit and reduce confusion with the fact it is a non-zero value and cannot be a default.
- Inputs (Internals): Renamed symbols global routes:
Renamed ImGuiInputFlags_RouteGlobalLow -> ImGuiInputFlags_RouteGlobal (this is the suggested global route)
Renamed ImGuiInputFlags_RouteGlobal -> ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused
Renamed ImGuiInputFlags_RouteGlobalHigh -> ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive
- Inputs (Internals): Shortcut(), SetShortcutRouting(): swapped last two parameters order
in function signatures:
Before: Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id = 0, ImGuiInputFlags flags = 0);
After: Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags = 0, ImGuiID owner_id = 0);
- Inputs (Internals): owner-aware versions of IsKeyPressed(), IsKeyChordPressed(), IsMouseClicked():
swapped last two parameters order in function signatures:
Before: IsKeyPressed(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags = 0);
After: IsKeyPressed(ImGuiKey key, ImGuiInputFlags flags, ImGuiID owner_id = 0);
Before: IsMouseClicked(ImGuiMouseButton button, ImGuiID owner_id, ImGuiInputFlags flags = 0);
After: IsMouseClicked(ImGuiMouseButton button, ImGuiInputFlags flags, ImGuiID owner_id = 0);
- For several reasons those changes makes sense. They were all made before making some of
those API public. Only past users of imgui_internal.h with the extra parameters will be affected.
Added asserts for valid flags in various functions to detect _some_ misuses, BUT NOT ALL.
Docking+Viewports Branch:
- Docking: *BREAKING* changed signature of DockSpaceOverViewport() to allow passing
an explicit dockspace id if desired. (#7611)
Before: DockSpaceOverViewport(const ImGuiViewport* viewport = NULL, ImGuiDockNodeFlags flags = 0, ...);
After: DockSpaceOverViewport(ImGuiID dockspace_id = 0, const ImGuiViewport* viewport = NULL, ImGuiDockNodeFlags flags = 0, ...);
Simply add a leading 0 to your existing calls to DockSpaceOverViewport() if you have any.
- Tables: resizing border hit-rect scales according to current monitor dpi scale.
-----------------------------------------------------------------------
VERSION 1.90.6 (Released 2024-05-08)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.90.6
Breaking changes:
- TreeNode: Fixed a layout inconsistency when using a empty/hidden label followed
by a SameLine() call. (#7505, #282)
Before: TreeNode("##Hidden"); SameLine(); Text("Hello");
// This was actually incorrect! BUT appeared to look ok with the default style
// where ItemSpacing.x == FramePadding.x * 2 (it didn't look aligned otherwise).
After: TreeNode("##Hidden"); SameLine(0, 0); Text("Hello");
// This is correct for all values in style.
With the fix, IF you were successfully using TreeNode("")+SameLine(); you will now
have extra spacing between your TreeNode and the following item. You'll need to change
the SameLine() call to SameLine(0,0) to remove this extraneous spacing.
This seemed like the more sensible fix that's not making things less consistent.
(Note: when using this idiom you are likely to also use ImGuiTreeNodeFlags_SpanAvailWidth).
Other changes:
- Windows: Changed default ClipRect to extend to windows' left and right borders,
instead of adding arbitrary WindowPadding.x * 0.5f space on left and right.
That ClipRect half-padding was arbitrary/confusing and inconsistent with Y axis.
It also made it harder to draw items covering whole window without pushing an
extended ClipRect. Some items near windows left and right edge that used to be clipped
may be partly more visible. (#3312, #7540, #3756, #6170, #6365)
- Windows: Fixed subsequent Begin() append calls from setting last item information
for title bar, making it impossible to use IsItemHovered() on a Begin()-to-append,
and causing issue bypassing hover detection on collapsed windows. (#7506, #823)
- Fonts: Fixed font ascent and descent calculation when a font hits exact integer values.
It is possible that some prior manual use of ImFontConfig::GlyphOffset may become
duplicate with this fix. (#7399, #7404) [@GamingMinds-DanielC]
- TreeNode: Added ImGuiTreeNodeFlags_SpanTextWidth to make hitbox and highlight only
cover the label. (#6937) [@dimateos]
- Tables: Angled headers: fixed multi-line label display when angle is flipped. (#6917)
- Tables: Angled headers: added style.TableAngledHeadersTextAlign and corresponding
ImGuiStyleVar_TableAngledHeadersTextAlign variable. Default to horizontal center. (#6917)
[@thedmd, @ocornut]
- ProgressBar: Added support for indeterminate progress bar by passing an animated
negative fraction, e.g. ProgressBar(-1.0f * GetTime()). (#5316, #5370, #1901)[@gan74]
- Text, DrawList: Improved handling of long single-line wrapped text. Faster and
mitigate issues with reading vertex indexing limits with 16-bit indices. (#7496, #5720)
- Backends: OpenGL3: Detect ES3 contexts on desktop based on version string,
to e.g. avoid calling glPolygonMode() on them. (#7447) [@afraidofdark, @ocornut]
- Backends: OpenGL3: Update loader for Linux to support EGL/GLVND. (#7562) [@ShadowNinja, @vanfanel]
- Backends: Vulkan: Added convenience support for Volk via IMGUI_IMPL_VULKAN_USE_VOLK define.
(you could always use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + ImGui_ImplVulkan_LoadFunctions() as well).
(#6582, #4854) [@adalsteinnh, @kennyalive, @ocornut]
- Backends: SDL3: Fixed text inputs. Re-enable calling SDL_StartTextInput()/SDL_StopTextInput()
as SDL3 no longer enables it by default. (#7452, #6306, #6071, #1953) [@Green-Sky]
- Examples: GLFW+Vulkan, SDL+Vulkan: Added optional support for Volk. (#6582, #4854)
- Examples: GLFW+WebGPU: Added support for WebGPU-native/Dawn (#7435, #7132) [@eliasdaler, @Zelif]
- Examples: GLFW+WebGPU: Renamed example_emscripten_wgpu/ to example_glfw_wgpu/. (#7435, #7132)
Docking+Viewports Branch:
- Docking: when io.ConfigDockingWithShift is enabled, fixed help tooltip erroneously
reading SetNextWindowXXX() data. (#6709, #4643, #7491) [@ocornut, @cfillion]
- Viewports: fixed outer-right edge of MenuBar clipping rectangle off by one when window
is located on a monitor with negative coordinates. (#6861, #2884) [@cfillion]
- Backends: Vulkan: reworked swap-chain resize handling for secondary viewports, fix for
typical Linux setups. (#2626, #3390, #3758, #7508, #7513) [@RoryO, @InsideBSITheSecond]
- Backends: Vulkan: create a custom pipeline for secondary viewports. Fixes issues
when user created main viewport uses a different renderpass. (#6325, #6305, #7398,
#3459, #3253, #3522) [@skaman, @FunMiles]
-----------------------------------------------------------------------
VERSION 1.90.5 (Released 2024-04-11)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.90.5
Breaking changes:
- More formally obsoleted GetKeyIndex() when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is set.
It has been unnecessary and a no-op since 1.87 (it returns the same value as passed
when used with a 1.87+ backend using io.AddKeyEvent() function). (#4921)
- IsKeyPressed(GetKeyIndex(ImGuiKey_XXX)) --> IsKeyPressed(ImGuiKey_XXX)
- ImDrawList: Merged the radius_x/radius_y parameters in AddEllipse(), AddEllipseFilled()
and PathEllipticalArcTo() into a single ImVec2 parameter. Exceptionally, because those
functions were added recently in 1.90, we are not adding inline redirection functions.
The transition is easy and should affect few users. (#2743, #7417) [@cfillion]
Other changes:
- Windows: Scrollbar visibility decision uses current size when both size and contents
size are submitted by API. (#7252)
- Windows: Double-click to collapse may be disabled via key-ownership mechanism. (#7369)
- Windows: BeginChild(): Extend outer resize borders to the edges when there are no corner
grips. Essentially affects resizable child windows. (#7440, #1710) [@cfillion]
- Windows: BeginChild(): Resizing logic for child windows evaluates whether per-axis clamping
should be applied based on parent scrollbars, not child scrollbars. (#7440, #1710) [@cfillion]
Adjust those resizing limits to match window padding rather than inner clipping rectangle.
- Tables: Fixed auto-width columns when using synced-instances of same table, width of
one instance would bleed into next one instead of sharing their widths. (#7218)
- Tables: Angled headers: fixed border hit box extending beyond when used within
non-scrollable tables. (#7416) [@cfillion]
- Tables: Angled headers: fixed borders not moving back up after TableAngleHeadersRow()
stops being called. (#7416) [@cfillion]
- Tables: Angled headers: rounding header size to nearest integers, fixes some issues
when using clipper.
- Menus, Popups: Fixed an issue where sibling menu popups re-opening in successive
frames would erroneously close the window. While it is technically a popup issue
it would generally manifest when fast moving the mouse bottom to top in a sub-menu.
(#7325, #7287, #7063)
- ProgressBar: Fixed passing fraction==NaN from leading to a crash. (#7451)
- ListBox: Fixed text-baseline offset when using SameLine()+Text() after a labeled ListBox().
- Drags, Sliders, Inputs: Fixed io.PlatformLocaleDecimalPoint decimal point localization
feature not working regression from 1.90.1. (#7389, #6719, #2278) [@GamingMinds-DanielC]
- Style: Added ImGuiStyleVar_TabBorderSize, ImGuiStyleVar_TableAngledHeadersAngle for
consistency. (#7411) [@cfillion]
- DrawList: Added AddConcavePolyFilled(), PathFillConcave() concave filling. (#760) [@thedmd]
Note that only simple polygons (no self-intersections, no holes) are supported.
- DrawList: Allow AddText() to accept null ranges. (#3615, 7391)
- Docs: added more wiki links to headers of imgui.h/imgui.cpp to facilitate discovery
of interesting resources, because github doesn't allow Wiki to be crawled by search engines.
- This is the main wiki: https://github.com/ocornut/imgui/wiki
- This is the crawlable version: https://github-wiki-see.page/m/ocornut/imgui/wiki
Adding a link to the crawlable version, even though it is not intended for humans,
to increase its search rank.
Docking+Viewports Branch:
- Backends: Win32: made it so that an appearing viewport showing up doesn't bring
its parent to front. (#7354)
-----------------------------------------------------------------------
VERSION 1.90.4 (Released 2024-02-22)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.90.4
Other changes:
- Nav: Fixed SetKeyboardFocusHere() or programmatic tabbing API from not working on
windows with the ImGuiWindowFlags_NoNavInputs flag (regression in 1.90.2, which
among other things broke imgui_memory_editor).
- Menus, Popups: Fixed an issue where hovering a parent-menu upward would
erroneously close the window. (#7325, #7287, #7063)
- Popups: Fixed resizable popup minimum size being too small. Standardized minimum
size logic. (#7329).
- Modals: Temporary changes of ImGuiCol_ModalWindowDimBg are properly handled by
BeginPopupModal(). (#7340)
- Tables: Angled headers: fixed support for multi-line labels. (#6917)
- Tables: Angled headers: various fixes to accurately handle CellPadding changes. (#6917)
- Tables: Angled headers: properly registers horizontal component of angled headers
for auto-resizing of columns. (#6917)
- Tables: Angled headers: fixed TableAngledHeadersRow() incorrect background fill
drawn too low, particularly visible with tables that have no scrolling. (#6917)
- ProgressBar: Fixed a minor tessellation issue when rendering rounded progress bars,
where in some situations the rounded section wouldn't follow regular tessellation rules.
- Debug Tools: Item Picker: Promoted ImGui::DebugStartItemPicker() to public API. (#2673)
- Debug Tools: Item Picker: Menu entry visible in Demo->Tools but greyed out unless
io.ConfigDebugIsDebuggerPresent is set. (#2673)
- Misc: Added optional alpha multiplier parameter to GetColorU32(ImU32) variant.
- Demo: Custom Rendering: better demonstrate PathArcTo(), PathBezierQuadraticCurveTo(),
PathBezierCubicCurveTo(), PathStroke(), PathFillConvex() functions.
Docking+Viewports Branch:
- Backends: GLFW: enable ImGuiBackendFlags_HasMouseHoveredViewport support with GLFW 3.3.x,
as required specs for it was relaxed in 1.87. This enable better viewport hovering detection
without GLFW 3.4's GLFW_MOUSE_PASSTHROUGH, with less reliance on dear imgui's own heuristic
of platform windows order. (#7316)
-----------------------------------------------------------------------
VERSION 1.90.3 (Released 2024-02-14)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.90.3
Breaking changes:
- Backends: SDL2: Removed obsolete ImGui_ImplSDL2_NewFrame(SDL_Window*) signature which
was obsoleted in 1.84. Calling ImGui_ImplSDL2_NewFrame() is fine.
- Backends: Vulkan: Moved RenderPass parameter from ImGui_ImplVulkan_Init() function to
ImGui_ImplVulkan_InitInfo structure. Not required when using dynamic rendering. (#7308) [@shawnhatori]
- Backends: Vulkan: Using dynamic rendering now require filling the PipelineRenderingCreateInfo
structure in ImGui_ImplVulkan_InitInfo, allowing to configure color/depth/stencil formats.
Removed ColorAttachmentFormat field previously provided for dynamic rendering.
(#7166, #6855, #5446, #5037) [@shawnhatori]
Other changes:
- Menus, Popups: Fixed menus and popups with ChildWindow flag erroneously not displaying
a scrollbar when contents is over parent viewport size. (#7287, #7063) [@ZingBallyhoo]
- Backends: SDL2, SDL3: Handle gamepad disconnection + fixed increasing gamepad reference
counter continuously. Added support for multiple simultaneous gamepads.
Added ImGui_ImplSDL2_SetGamepadMode()) function to select whether to automatically pick
first available gamepad, all gamepads, or specific gamepads.
(#3884, #6559, #6890, #7180) [@ocornut, @lethal-guitar, @wn2000, @bog-dan-ro]
- Backends: SDL3: Fixed gamepad handling. (#7180) [@bog-dan-ro]
- Backends: SDLRenderer3: query newly added SDL_RenderViewportSet() to not restore
a wrong viewport if none was initially set.
- Backends: DirectX9: Using RGBA format when allowed by the driver to avoid CPU side
conversion. (#6575) [@Demonese]
- Internals: Fixed ImFileOpen not working before context is created, preventing creation
of a font atlas before main context creation. (#7314, #7315) [@PathogenDavid, @ocornut]
-----------------------------------------------------------------------
VERSION 1.90.2 (Released 2024-02-09)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.90.2
Breaking changes:
- Commented out ImGuiIO::ImeWindowHandle obsoleted in 1.87 in favor of writing
to 'void* ImGuiViewport::PlatformHandleRaw'.
- Backends: WebGPU: ImGui_ImplWGPU_Init() now takes a ImGui_ImplWGPU_InitInfo structure
instead of variety of parameters, allowing for easier further changes. (#7240)
Other changes:
- Nav: keyboard/gamepad activation mark widgets as held to give better visual feedback.
- Nav: tweak to logic marking navigated item as hovered when using keyboard, allowing
the hover highlight to stay even while another item is activated.
- Nav: Fixed SetKeyboardFocusHere() not working when current nav focus is in different scope,
regression from 1.90.1 related to code scoping Tab presses to local scope. (#7226) [@bratpilz]
- Nav: Fixed pressing Escape while in a child window with _NavFlattened flag. (#7237)
- Nav: Improve handling of Alt key to toggle menu so that key ownership may be claimed on
individual left/right alt key without interfering with the other.
- Nav, Menus: Fixed click on a BeginMenu() followed by right-arrow from making the child menu
reopen and flicker (using ImGuiPopupFlags_NoReopen).
- Nav: ImGuiWindowFlags_NoNavInputs is tested during scoring so NavFlattened windows can use it.
- Popups: OpenPopup(): added ImGuiPopupFlags_NoReopen flag to specifically not close and reopen
a popup when it is already open. (#1497, #1533)
(Note that this differs from specific handling we already have in place for the case of calling
OpenPopup() repeatedly every frame: we already didn't reopen in that specific situation, otherwise
the effect would be very disastrous in term of confusion, as reopening would steal focus).
- Popups: Slight change to popup closing logic (e.g. after focusing another window) which skipped
over popups that are also child windows.
- Combo: Fixed not reusing windows optimally when used inside a popup stack.
- Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect.
- Debug Tools: Metrics: Improved Monitors and Viewports minimap display. Highlight on hover.
- Debug Tools: Debug Log: Added "Input Routing" logging.
- Debug Tools: Added "nop" to IM_DEBUG_BREAK macro on GCC to work around GDB bug (#7266) [@Peter0x44]
- Backends: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by
allocating one extra semaphore than in-flight frames. (#7236) [@mklefrancois]
- Backends: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size. (#3957)
- Backends: Vulkan: Fixed handling of ImGui_ImplVulkan_InitInfo::MinAllocationSize field. (#7189, #4238)
- Backends: WebGPU: Added ImGui_ImplWGPU_InitInfo::PipelineMultisampleState. (#7240)
- Backends: WebGPU: Filling all WGPUDepthStencilState fields explicitly as a recent Dawn
update stopped setting default values. (#7232) [@GrigoryGraborenko]
- Backends: WebGPU: Fixed pipeline layout leak. (#7245) [@rajveermalviya]
- Backends: OpenGL3: Backup and restore GL_PIXEL_UNPACK_BUFFER. (#7253)
- Internals: Many improvements related to yet unpublicized shortcut routing and input ownership systems.
- Internals: InputText: Added internal helpers to force reload of user-buf when active. (#2890) [@kudaba, @ocornut]
Often requested in some form (#6962, #5219, #3290, #4627, #5054, #3878, #2881, #1506, #1216, #968),
and useful for interactive completion/suggestions popups (#2057, #718)
Docking+Viewports Branch:
- Added ImGuiWindowClass::FocusRouteParentWindowId as a way to connect the focus route between
a tool window to a parent document window, so that Shortcuts in the documents are routed when the
tool is focused (regardless of whether the tool is docked or in a floating viewport, etc.) (#6798)
- Added ImGuiDockNodeFlags_DockedWindowsInFocusRoute to automatically make a dockspace connect
the focus route of its docked window. This is provided a convenience in case you have windows
where a connection is not explicit. (#6798)
- Viewports: Fixed moving accross monitors when io.ConfigWindowsMoveFromTitleBarOnly is set. (#7299, #3071)
- Backends: OSX: Fixed not submitting Monitors info when viewports are not enabled, leading to
missing e.g. DpiScale info. (#7257) [@actboy168]
-----------------------------------------------------------------------
VERSION 1.90.1 (Released 2024-01-10)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.90.1
Breaking changes:
- imgui_freetype: commented out ImGuiFreeType::BuildFontAtlas() obsoleted in 1.81.
Prefer using #define IMGUI_ENABLE_FREETYPE or see commented code for manual calls.
- Removed CalcListClipping() marked obsolete in 1.86. (#3841)
Prefer using ImGuiListClipper which can return non-contiguous ranges.
- Internals, Columns: commented out legacy ImGuiColumnsFlags_XXX symbols redirecting
to ImGuiOldColumnsFlags_XXX, obsoleted from imgui_internal.h in 1.80.
- Commented out obsolete ImGuiKey_KeyPadEnter redirection to ImGuiKey_KeypadEnter. (#2625, #7143)
Other changes:
- Windows:
- BeginChild(): Fixed auto-resizing erroneously limiting size to host viewport
minus padding. There are no limit to a child width/height. (#7063) [@Devyre]
- BeginChild(): Resize borders rendered even when ImGuiWindowFlags_NoBackground
is specified. (#1710, #7194)
- Fixed some auto-resizing path using style.WindowMinSize.x (instead of x/y)
for both axises since 1.90. (#7106) [@n0bodysec]
- Scrolling: internal scrolling value is rounded instead of truncated, as a way to reduce
speed asymmetry when (incorrectly) attempting to scroll by non-integer amount. (#6677)
- Navigation (Keyboard/gamepad):
- Nav, IO: SetNextFrameWantCaptureKeyboard(false) calls are not overridden back to true when
navigation is enabled. SetNextFrameWantCaptureKeyboard() is always higher priority. (#6997)
- Nav: Activation can also be performed with Keypad Enter. (#5606)
- Drag and Drop:
- Fixed drop target highlight on items temporarily pushing a widened clip rect
(namely Selectables and Treenodes using SpanAllColumn flag) so the highlight properly covers
all columns. (#7049, #4281, #3272)
- InputText:
- InputTextMultiline: Fixed Tab character input not repeating (1.89.4 regression).
- InputTextMultiline: Tabbing through a multi-line text editor which allows Tab character inputs
(using the ImGuiInputTextFlags_AllowTabInput flag) doesn't automatically activate it, in order
to allow passing through multiple widgets easily. (#3092, #5759, #787)
- Drags, Sliders, Inputs:
- DragScalarN, SliderScalarN, InputScalarN: Fixed incorrect pushes into ItemWidth
stack when number of components is 1. [#7095] [@Nahor]
- Drags, Sliders, Inputs: removed all attempts to filter non-numerical characters during text
editing. Invalid inputs not applied to value, visibly reverted after validation. (#6810, #7096)
- Drags, Sliders, Inputs: removal of filter means that "nan" and "inf" values may be input. (#7096)
- DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: improve multi-components
width computation to better distribute the error. (#7120, #7121) [@Nahor]
- Menus:
- Tweaked hover slack logic, adding an extra timeout to avoid situations where a slow vertical
movements toward another parent BeginMenu() can keep the wrong child menu open. (#6671, #6926)
- Color Editors:
- ColorEdit: Layout tweaks for very small sizes. (#7120, #7121)
- ColorPicker: Fixed saturation/value cursor radius not scaling properly.
- Tabs: Added ImGuiTabItemFlags_NoAssumedClosure to enable app to react on closure attempt,
without having to draw an unsaved document marker (ImGuiTabItemFlags_UnsavedDocument sets
_NoAssumedClosure automatically). (#7084)
- Debug Tools:
- Added io.ConfigDebugIsDebuggerPresent option. When enabled, this adds buttons in various
locations of Metrics/Debugger to manually request a debugger break:
- Request a debug break in a Begin() call.
- Request a debug break in a ItemAdd() call via debug log and hovering 0xXXXXXX identifiers.
- Request a debug break in a BeginTable() call.
- Request a debug break in a SetShortcutRouting()/Shortcut() call. [Internal]
- Metrics: Reorganize Tools menu.
- Added DebugFlashStyleColor() to identify a style color. Added to Style Editor.
- Debug Log: Hide its own clipper log to reduce noise in the output. (#5855)
- Debug Log: Clicking any filter with SHIFT held enables it for 2 frames only,
making it easier when dealing with spammy logs. (#5855)
- Settings: Fixed an issue marking settings as dirty when merely clicking on a border or resize
grip without moving it.
- Misc: Added IMGUI_USER_H_FILENAME to change the path included when using
IMGUI_INCLUDE_IMGUI_USER_H. (#7039) [@bryceberger]
- Misc: Rework debug display of texture id in Metrics window to avoid compile-error when
ImTextureID is defined to be larger than 64-bits. (#7090)
- Misc: Added extra courtesy ==/!= operators when IMGUI_DEFINE_MATH_OPERATORS is defined.
- Misc: Fixed text functions fast-path for handling "%s" and "%.*s" to handle null pointers gracefully,
like most printf implementations. (#7016, #3466, #6846) [@codefrog2002]
- Misc: Renamed some defines in imstb_textedit.h to avoid conflicts when using unity/jumbo builds
on a codebase where another copy of the library is used.
- Misc: During shutdown, check that io.BackendPlatformUserData and io.BackendRendererUserData are NULL
in order to catch cases where backend was not shut down. (#7175)
- Misc: Reworked Issue Template to a shinier and better form. (#5927) [@Panquesito7, @PathogenDavid, @ocornut]
- Backends:
- GLFW, Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to
register canvas selector and auto-resize GLFW window. (#6751) [@Traveller23, @ypujante]
- GLFW: Fixed Windows specific hooks to use Unicode version of WndProc even when
compiling in MBCS mode. (#7174) [@kimidaisuki22]
- OpenGL3: Update GL3W based imgui_impl_opengl3_loader.h to load libGL.so variants in
case of missing symlink. Fix 1.90 regression for some distros. (#6983)
- Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs
vkDestroyCommandPool(). (#7075) [@FoonTheRaccoon]
- Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous
"best practice" validation layer. (#7189, #4238) [@philae-ael]
- Vulkan: Stopped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT
as we don't reset them.
- WebGPU: Fixed wgpuRenderPassEncoderSetScissorRect() crash when rendering modal window's
dimming layer, which has an unclipped value in ImDrawCmd::ClipRect. (#7191) [@aparis69]
- Examples:
- Examples: GLFW+Emscripten: Fixed examples not consistently resizing according to host canvas.
(#6751) [@Traveller23, @ypujante]
- Examples: SDL3: Minor fixes following recent SDL3 in-progress development.
Docking+Viewports Branch:
- Windows: Fixed ImGuiCol_TitleBg/Active alpha being used for viewport-owned windows. (#7181) [@PathogenDavid]
- Backends: DX12: Changed swapchain scaling mode to DXGI_SCALING_NONE to reduce artifacts as
queued frames aren't synchronized with platform window resizes. (#7152, #7153) [@SuperWangKai]
- Backends: OSX: Fixed monitor and window position by correctly transforming Y origin on multi-viewports
multi-monitor setups. (#7028, #7101, #6009, #6432) [@dmirty-kuzmenko, @734vin]
- Backends: OSX: Fixed IME position in multi-monitor multi-viewports setups. (#7028) [@734vin]
-----------------------------------------------------------------------
VERSION 1.90.0 (Released 2023-11-15)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.90
Breaking changes:
- BeginChild(): Upgraded 'bool border = false' parameter to 'ImGuiChildFlags flags = 0'.
@@ -153,7 +698,7 @@ Other changes:
with ImGuiDragDropFlags_AcceptNoPreviewTooltip and submitting a tooltip manually.
- Tables:
- Added angled headers support. You need to set ImGuiTableColumnFlags_AngledHeader on selected
columns and call TableAngledHeadersRow(). Added style.TableAngledHeadersAngle style option.
columns and call TableAngledHeadersRow(). Added style.TableAngledHeadersAngle style option. (#6917)
- Added ImGuiTableFlags_HighlightHoveredColumn flag, currently highlighting column header.
- Fixed an edge-case when no columns are visible + table scrollbar is visible + user
code is always testing return value of TableSetColumnIndex() to coarse clip. With an active
@@ -539,7 +1084,7 @@ Breaking changes:
- ListBoxFooter() -> use EndListBox()
- Note how two variants of ListBoxHeader() existed. Check commented versions in imgui.h for refeence.
- Backends: SDL_Renderer: Renamed 'imgui_impl_sdlrenderer.h/cpp' to 'imgui_impl_sdlrenderer2.h/cpp',
in order to accomodate for upcoming SDL3 and change in its SDL_Renderer API. (#6286)
in order to accommodate for upcoming SDL3 and change in its SDL_Renderer API. (#6286)
- Backends: GLUT: Removed call to ImGui::NewFrame() from ImGui_ImplGLUT_NewFrame().
It needs to be called from the main app loop, like with every other backends. (#6337) [@GereonV]
@@ -1149,7 +1694,7 @@ Other Changes:
- Backends: Metal: Use __bridge for ARC based systems. (#5403) [@stack]
- Backends: Metal: Add dispatch synchronization. (#5447) [@luigifcruz]
- Backends: Metal: Update deprecated property 'sampleCount'->'rasterSampleCount'. (#5603) [@dcvz]
- Backends: Vulkan: Added experimental ImGui_ImplVulkan_RemoveTexture() for api symetry. (#914, #5738).
- Backends: Vulkan: Added experimental ImGui_ImplVulkan_RemoveTexture() for api symmetry. (#914, #5738).
- Backends: WebGPU: fixed rendering when a depth buffer is enabled. (#5869) [@brainlag]
Docking+Viewports Branch:
@@ -2062,7 +2607,7 @@ Other Changes:
alpha compositing and transparent windows. (#2766, #3447 etc.).
- Backends: OpenGL, Vulkan, DX9, DX10, DX11, DX12, Metal, WebGPU, Allegro: Rework blending equation to
preserve alpha in output buffer (using SrcBlendAlpha = ONE, DstBlendAlpha = ONE_MINUS_SRC_ALPHA consistently
accross all backends), facilitating compositing of the output buffer with another buffer.
across all backends), facilitating compositing of the output buffer with another buffer.
(#2693, #2764, #2766, #2873, #3447, #3813, #3816) [@ocornut, @thedmd, @ShawnM427, @Ubpa, @aiekick]
- Backends: DX9: Fix to support IMGUI_USE_BGRA_PACKED_COLOR. (#3844) [@Xiliusha]
- Backends: DX9: Fix to support colored glyphs, using newly introduced 'TexPixelsUseColors' info. (#3844)
@@ -5619,7 +6164,7 @@ Other Changes:
VERSION 1.08 (2014-08-25)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.09
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.08
- Fixed ImGuiTextFilter trimming of leading/trailing blanks.
- Fixed file descriptor leak on LoadSettings() failure.

View File

@@ -58,7 +58,7 @@ Steps:
- Be mindful that messages are being sent to the mailbox of "Watching" users. Try to proofread your messages before sending them. Edits are not seen by those users unless they browse the site.
**Some unfortunate words of warning**
- If you are involved in cheating schemes (e.g. DLL injection) for competitive online multiplayer games, please don't post here. We won't answer and you will be blocked. It doesn't matter if your question relates to said project. We've had too many of you and need to project our time and sanity.
- If you are involved in cheating schemes (e.g. DLL injection) for competitive online multiplayer games, please don't post here. We won't answer and you will be blocked. It doesn't matter if your question relates to said project. We've had too many of you and need to protect our time and sanity.
- Due to frequent abuse of this service from the aforementioned users, if your GitHub account is anonymous and was created five minutes ago please understand that your post will receive more scrutiny and incomplete questions will be harshly dismissed.
If you have been using Dear ImGui for a while or have been using C/C++ for several years or have demonstrated good behavior here, it is ok to not fulfill every item to the letter. Those are guidelines and experienced users or members of the community will know which information is useful in a given context.

View File

@@ -104,8 +104,8 @@ OSX + OpenGL2 example. <BR>
(NB: imgui_impl_osx.mm is currently not as feature complete as other platforms backends.
You may prefer to use the GLFW Or SDL backends, which will also support Windows and Linux.)
[example_emscripten_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_emscripten_wgpu/) <BR>
Emcripten + GLFW + WebGPU example. <BR>
[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>
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_wgpu.cpp
Note that the 'example_glfw_opengl3' and 'example_sdl2_opengl3' examples also supports Emscripten!
@@ -126,7 +126,7 @@ state, and might confuse your GPU driver. One star, not recommended.
GLFW (Win32, Mac, Linux) + OpenGL3+/ES2/ES3 example (modern, programmable pipeline). <BR>
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp <BR>
This uses more modern GL calls and custom shaders.<BR>
This support building with Emscripten and targetting WebGL.<BR>
This support building with Emscripten and targeting WebGL.<BR>
Prefer using that if you are using modern GL or WebGL in your application.
[example_glfw_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_vulkan/) <BR>
@@ -168,7 +168,7 @@ state, and might confuse your GPU driver. One star, not recommended.
SDL2 (Win32, Mac, Linux, etc.) + OpenGL3+/ES2/ES3 example. <BR>
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_opengl3.cpp <BR>
This uses more modern GL calls and custom shaders. <BR>
This support building with Emscripten and targetting WebGL.<BR>
This support building with Emscripten and targeting WebGL.<BR>
Prefer using that if you are using modern GL or WebGL in your application.
[example_sdl2_sdlrenderer2/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_sdlrenderer2/) <BR>

View File

@@ -23,7 +23,7 @@ or view this file with any Markdown viewer.
| [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) |
| [I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-displaying-outside-their-expected-windows-boundaries) |
| **Q&A: Usage** |
| **[About the ID Stack system..<br>Why is my widget not reacting when I click on it?<br>How can I have widgets with an empty label?<br>How can I have multiple widgets with the same label?<br>How can I have multiple windows with the same label?](#q-about-the-id-stack-system)** |
| **[About the ID Stack system..<br>Why is my widget not reacting when I click on it?<br>Why is the wrong widget reacting when I click on one?<br>How can I have widgets with an empty label?<br>How can I have multiple widgets with the same label?<br>How can I have multiple windows with the same label?](#q-about-the-id-stack-system)** |
| [How can I display an image? What is ImTextureID, how does it work?](#q-how-can-i-display-an-image-what-is-imtextureid-how-does-it-work)|
| [How can I use maths operators with ImVec2?](#q-how-can-i-use-maths-operators-with-imvec2) |
| [How can I use my own maths types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-maths-types-instead-of-imvec2imvec4) |
@@ -199,10 +199,42 @@ ctx->RSSetScissorRects(1, &r);
### Q: About the ID Stack system...
### Q: Why is my widget not reacting when I click on it?
### Q: Why is the wrong widget reacting when I click on one?
### Q: How can I have widgets with an empty label?
### Q: How can I have multiple widgets with the same label?
### Q: How can I have multiple windows with the same label?
**USING THE SAME LABEL+ID IS THE MOST COMMON USER MISTAKE:**
<table>
<tr>
<td><img src="https://github.com/ocornut/imgui/assets/8225057/76eb9467-74d1-4e95-9f56-be81c6dd029d"></td>
<td>
<pre lang="cpp">
ImGui::Begin("Incorrect!");
ImGui::DragFloat2("My value", &objects[0]->pos.x);
ImGui::DragFloat2("My value", &objects[1]->pos.x);
ImGui::DragFloat2("My value", &objects[2]->pos.x);
ImGui::End();
&nbsp;
ImGui::Begin("Correct!");
ImGui::DragFloat2("My value", &objects[0]->pos.x);
ImGui::DragFloat2("My value##2", &objects[1]->pos.x);
ImGui::DragFloat2("My value##3", &objects[2]->pos.x);
ImGui::End();
&nbsp;
ImGui::Begin("Also Correct!");
for (int n = 0; n < 3; n++)
{
ImGui::PushID(n);
ImGui::DragFloat2("My value", &objects[n]->pos.x);
ImGui::PopID();
}
ImGui::End();
</pre>
</td>
</tr>
</table>
A primer on labels and the ID Stack...
Dear ImGui internally needs to uniquely identify UI elements.
@@ -426,7 +458,7 @@ Finally, you may call `ImGui::ShowMetricsWindow()` to explore/visualize/understa
### Q: How can I use maths operators with ImVec2?
We do not export maths operators by default in imgui.h in order to not conflict with the use of your own maths types and maths operators. As a convenience, you may use `#defne IMGUI_DEFINE_MATH_OPERATORS` + `#include "imgui.h"` to access our basic maths operators.
We do not export maths operators by default in imgui.h in order to not conflict with the use of your own maths types and maths operators. As a convenience, you may use `#define IMGUI_DEFINE_MATH_OPERATORS` + `#include "imgui.h"` to access our basic maths operators.
##### [Return to Index](#index)
@@ -621,8 +653,8 @@ You may take a look at:
- [Quotes](https://github.com/ocornut/imgui/wiki/Quotes)
- [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui)
- [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors)
- [Gallery](https://github.com/ocornut/imgui/issues/6897)
- [Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding)
- [Gallery](https://github.com/ocornut/imgui/issues/7503)
##### [Return to Index](#index)
@@ -664,11 +696,11 @@ There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/ci
# Q&A: Community
### Q: How can I help?
- Businesses: please reach out to `omar AT dearimgui.com` if you work in a place using Dear ImGui! We can discuss ways for your company to fund development via invoiced technical support, maintenance, or sponsoring contacts. This is among the most useful thing you can do for Dear ImGui. With increased funding, we can hire more people to work on this project.
- Businesses: please reach out to `omar AT dearimgui.com` if you work in a place using Dear ImGui! We can discuss ways for your company to fund development via invoiced technical support, maintenance, or sponsoring contacts. This is among the most useful thing you can do for Dear ImGui. With increased funding, we can hire more people to work on this project. Please see [Funding](https://github.com/ocornut/imgui/wiki/Funding) page.
- Individuals: you can support continued maintenance and development via PayPal donations. See [README](https://github.com/ocornut/imgui/blob/master/docs/README.md).
- If you are experienced with Dear ImGui and C++, look at [GitHub Issues](https://github.com/ocornut/imgui/issues), [GitHub Discussions](https://github.com/ocornut/imgui/discussions), the [Wiki](https://github.com/ocornut/imgui/wiki), read [docs/TODO.txt](https://github.com/ocornut/imgui/blob/master/docs/TODO.txt), and see how you want to help and can help!
- Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere, etc.
You may post screenshots or links in the [gallery threads](https://github.com/ocornut/imgui/issues/6897). Visuals are ideal as they inspire other programmers. Disclosing your use of Dear ImGui helps the library grow credibility, and helps other teams and programmers with taking decisions.
You may post screenshots or links in the [gallery threads](https://github.com/ocornut/imgui/issues/7503). Visuals are ideal as they inspire other programmers. Disclosing your use of Dear ImGui helps the library grow credibility, and helps other teams and programmers with taking decisions.
- If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues or sometimes incomplete PR.
##### [Return to Index](#index)

View File

@@ -53,7 +53,7 @@ All loaded fonts glyphs are rendered into a single texture atlas ahead of time.
This is often of byproduct of point 3. If you have large number of glyphs or multiple fonts, the texture may become too big for your graphics API. **The typical result of failing to upload a texture is if every glyph or everything appears as empty black or white rectangle.** Mind the fact that some graphics drivers have texture size limitation. If you are building a PC application, mind the fact that your users may use hardware with lower limitations than yours.
Some solutions:
- You may reduce oversampling, e.g. `font_config.OversampleH = 1`, this will half your texture size for a quality looss.
- You may reduce oversampling, e.g. `font_config.OversampleH = 1`, this will half your texture size for a quality loss.
Note that while OversampleH = 2 looks visibly very close to 3 in most situations, with OversampleH = 1 the quality drop will be noticeable. Read about oversampling [here](https://github.com/nothings/stb/blob/master/tests/oversample).
- Reduce glyphs ranges by calculating them from source localization data.
You can use the `ImFontGlyphRangesBuilder` for this purpose and rebuilding your atlas between frames when new characters are needed. This will be the biggest win!
@@ -404,16 +404,12 @@ ImGui::Text(u8"こんにちは"); // this will always be encoded as UTF-8
ImGui::Text("こんにちは"); // the encoding of this is depending on compiler settings/flags and may be incorrect.
```
Since C++20, because the C++ committee hate its users, they decided to change the `u8""` syntax to not return `const char*` but a new type `const char_t*` which doesn't cast to `const char*`.
Since C++20, because the C++ committee hate its users, they decided to change the `u8""` syntax to not return `const char*` but a new type `const char8_t*` which doesn't cast to `const char*`.
Because of type usage of `u8""` in C++20 is a little more tedious:
```cpp
ImGui::Text((const char*)u8"こんにちは");
```
We suggest using a macro in your codebase:
```cpp
#define U8(_S) (const char*)u8##_S
ImGui::Text(U8("こんにちは"));
```
However, you can disable this behavior completely using the compiler option [`/Zc:char8_t-`](https://learn.microsoft.com/en-us/cpp/build/reference/zc-char8-t?view=msvc-170) for MSVC and [`-fno-char8_t`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1423r3.html) for Clang and GCC.
##### [Return to Index](#index)
---------------------------------------
@@ -486,7 +482,7 @@ Some fonts files are available in the `misc/fonts/` folder:
#### MONOSPACE FONTS
Pixel Perfect:
- Proggy Fonts, by Tristan Grimmer http://www.proggyfonts.net or http://upperbounds.net
- Proggy Fonts, by Tristan Grimmer http://www.proggyfonts.net or http://upperboundsinteractive.com/fonts.php
- Sweet16, Sweet16 Mono, by Martin Sedlak (Latin + Supplemental + Extended A) https://github.com/kmar/Sweet16Font (also include an .inl file to use directly in dear imgui.)
Regular:

View File

@@ -11,12 +11,12 @@ Dear ImGui
Businesses: support continued development and maintenance via invoiced sponsoring/support contracts:
<br>&nbsp;&nbsp;_E-mail: contact @ dearimgui dot com_
<br>Individuals: support continued development and maintenance [here](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WGHNC6MBFLZ2S). Also see [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors) page.
<br>Individuals: support continued development and maintenance [here](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WGHNC6MBFLZ2S). Also see [Funding](https://github.com/ocornut/imgui/wiki/Funding) page.
| [The Pitch](#the-pitch) - [Usage](#usage) - [How it works](#how-it-works) - [Releases & Changelogs](#releases--changelogs) - [Demo](#demo) - [Integration](#integration) |
:----------------------------------------------------------: |
| [Gallery](#gallery) - [Support, FAQ](#support-frequently-asked-questions-faq) - [How to help](#how-to-help) - [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors) - [Credits](#credits) - [License](#license) |
| [Wiki](https://github.com/ocornut/imgui/wiki) - [Languages & frameworks backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [User quotes](https://github.com/ocornut/imgui/wiki/Quotes) |
| [Gallery](#gallery) - [Support, FAQ](#support-frequently-asked-questions-faq) - [How to help](#how-to-help) - **[Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding)** - [Credits](#credits) - [License](#license) |
| [Wiki](https://github.com/ocornut/imgui/wiki) - [Extensions](https://github.com/ocornut/imgui/wiki/Useful-Extensions) - [Languages bindings & frameworks backends](https://github.com/ocornut/imgui/wiki/Bindings) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [User quotes](https://github.com/ocornut/imgui/wiki/Quotes) |
### The Pitch
@@ -39,7 +39,7 @@ Dear ImGui is particularly suited to integration in game engines (for tooling),
### Usage
**The core of Dear ImGui is self-contained within a few platform-agnostic files** which you can easily compile in your application/engine. They are all the files in the root folder of the repository (imgui*.cpp, imgui*.h). **No specific build process is required**. You can add the .cpp files into your existing project.
**The core of Dear ImGui is self-contained within a few platform-agnostic files** which you can easily compile in your application/engine. They are all the files in the root folder of the repository (imgui*.cpp, imgui*.h). **No specific build process is required**. You can add the .cpp files into your existing project.
**Backends for a variety of graphics API and rendering platforms** are provided in the [backends/](https://github.com/ocornut/imgui/tree/master/backends) folder, along with example applications in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. You may also create your own backend. Anywhere where you can render textured triangles, you can render Dear ImGui.
@@ -110,7 +110,7 @@ Reading the changelogs is a good way to keep up to date with the things Dear ImG
Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing a variety of features and examples. The code is always available for reference in `imgui_demo.cpp`. [Here's how the demo looks](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/v167-misc.png).
You should be able to build the examples from sources. If you don't, let us know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here:
- [imgui-demo-binaries-20230704.zip](https://www.dearimgui.com/binaries/imgui-demo-binaries-20230704.zip) (Windows, 1.89.7, built 2023/07/04, master) or [older binaries](https://www.dearimgui.com/binaries).
- [imgui-demo-binaries-20240105.zip](https://www.dearimgui.com/binaries/imgui-demo-binaries-20240105.zip) (Windows, 1.90.1 WIP, built 2024/01/05, master) or [older binaries](https://www.dearimgui.com/binaries).
The demo applications are not DPI aware so expect some blurriness on a 4K screen. For DPI awareness in your application, you can load/reload your font at a different scale and scale your style with `style.ScaleAllSizes()` (see [FAQ](https://www.dearimgui.com/faq)).
@@ -139,7 +139,9 @@ Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas.
### Gallery
For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/6897)!
Examples projects using Dear ImGui: [Tracy](https://github.com/wolfpld/tracy) (profiler), [ImHex](https://github.com/WerWolv/ImHex) (hex editor/data analysis), [RemedyBG](https://remedybg.itch.io/remedybg) (debugger) and [hundreds of others](https://github.com/ocornut/imgui/wiki/Software-using-Dear-ImGui).
For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/7503)!
For a list of third-party widgets and extensions, check out the [Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page.
@@ -160,6 +162,8 @@ See: [Upcoming Changes](https://github.com/ocornut/imgui/wiki/Upcoming-Changes).
See: [Dear ImGui Test Engine + Test Suite](https://github.com/ocornut/imgui_test_engine) for Automation & Testing.
For the purposes of getting search engines to crawl the wiki, here's a link to the [Crawlable Wiki](https://github-wiki-see.page/m/ocornut/imgui/wiki) (not for humans, [here's why](https://github-wiki-see.page/)).
Getting started? For first-time users having issues compiling/linking/running or issues loading fonts, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions). For ANY other questions, bug reports, requests, feedback, please post on [GitHub Issues](https://github.com/ocornut/imgui/issues). Please read and fill the New Issue template carefully.
Private support is available for paying business customers (E-mail: _contact @ dearimgui dot com_).
@@ -170,7 +174,7 @@ We occasionally tag [Releases](https://github.com/ocornut/imgui/releases) (with
**Who uses Dear ImGui?**
See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes), [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors), and [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for an idea of who is using Dear ImGui. Please add your game/software if you can! Also, see the [Gallery Threads](https://github.com/ocornut/imgui/issues/6897)!
See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes), [Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding), and [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for an idea of who is using Dear ImGui. Please add your game/software if you can! Also, see the [Gallery Threads](https://github.com/ocornut/imgui/issues/7503)!
How to help
-----------
@@ -180,13 +184,13 @@ How to help
- See [GitHub Forum/Issues](https://github.com/ocornut/imgui/issues).
- You may help with development and submit pull requests! Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance forever. PR should be crafted both in the interest of the end-users and also to ease the maintainer into understanding and accepting it.
- See [Help wanted](https://github.com/ocornut/imgui/wiki/Help-Wanted) on the [Wiki](https://github.com/ocornut/imgui/wiki/) for some more ideas.
- Be a [sponsor](https://github.com/ocornut/imgui/wiki/Sponsors)! Have your company financially support this project via invoiced sponsors/maintenance or by buying a license for [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine) (please reach out: omar AT dearimgui DOT com).
- Be a [Funding Supporter](https://github.com/ocornut/imgui/wiki/Funding)! Have your company financially support this project via invoiced sponsors/maintenance or by buying a license for [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine) (please reach out: omar AT dearimgui DOT com).
Sponsors
--------
Ongoing Dear ImGui development is and has been financially supported by users and private sponsors.
<BR>Please see the **[detailed list of current and past Dear ImGui supporters](https://github.com/ocornut/imgui/wiki/Sponsors)** for details.
<BR>Please see the **[detailed list of current and past Dear ImGui funding supporters and sponsors](https://github.com/ocornut/imgui/wiki/Funding)** for details.
<BR>From November 2014 to December 2019, ongoing development has also been financially supported by its users on Patreon and through individual donations.
**THANK YOU to all past and present supporters for helping to keep this project alive and thriving!**
@@ -203,11 +207,11 @@ Developed by [Omar Cornut](https://www.miracleworld.net) and every direct or ind
Recurring contributors include Rokas Kupstys [@rokups](https://github.com/rokups) (2020-2022): a good portion of work on automation system and regression tests now available in [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine).
Sponsoring, maintenance/support contracts and other B2B transactions are hosted and handled by [Disco Hello](https://www.discohello.com).
Maintenance/support contracts, sponsoring invoices and other B2B transactions are hosted and handled by [Disco Hello](https://www.discohello.com).
Omar: "I first discovered the IMGUI paradigm at [Q-Games](https://www.q-games.com) where Atman Binstock had dropped his own simple implementation in the codebase, which I spent quite some time improving and thinking about. It turned out that Atman was exposed to the concept directly by working with Casey. When I moved to Media Molecule I rewrote a new library trying to overcome the flaws and limitations of the first one I've worked with. It became this library and since then I have spent an unreasonable amount of time iterating and improving it."
Embeds [ProggyClean.ttf](http://upperbounds.net) font by Tristan Grimmer (MIT license).
Embeds [ProggyClean.ttf](https://www.proggyfonts.net) font by Tristan Grimmer (MIT license).
<br>Embeds [stb_textedit.h, stb_truetype.h, stb_rect_pack.h](https://github.com/nothings/stb/) by Sean Barrett (public domain).
Inspiration, feedback, and testing for early versions: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. Also thank you to everyone posting feedback, questions and patches on GitHub.

View File

@@ -39,7 +39,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- scrolling: forward mouse wheel scrolling to parent window when at the edge of scrolling limits? (useful for listbox,tables?)
- scrolling/style: shadows on scrollable areas to denote that there is more contents (see e.g. DaVinci Resolve ui)
- drawdata: make it easy to deep-copy (or swap?) a full ImDrawData so user can easily save that data if they use threaded rendering. (e.g. #2646)
- drawdata: make it easy to deep-copy (or swap?) a full ImDrawData so user can easily save that data if they use threaded rendering. (#1860 see ImDrawDataSnapshot)
! drawlist: add CalcTextSize() func to facilitate consistent code from user pov (currently need to use ImGui or ImFont alternatives!)
- drawlist: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command). (WIP branch)
- drawlist: make it easier to toggle AA per primitive, so we can use e.g. non-AA fill + AA borders more naturally
@@ -117,7 +117,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
!- color: the color conversion helpers/types are a mess and needs sorting out.
- color: (api breaking) ImGui::ColorConvertXXX functions should be loose ImColorConvertXX to match imgui_internals.h
- plot: full featured plot/graph api w/ scrolling, zooming etc. --> ImPlot
- plot: full featured plot/graph api w/ scrolling, zooming etc. --> promote using ImPlot
- (plot: deleted all other todo lines on 2023-06-28)
- clipper: ability to disable the clipping through a simple flag/bool.
@@ -178,7 +178,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- drag float: power != 0.0f with current value being outside the range keeps the value stuck.
- drag float: added leeway on edge (e.g. a few invisible steps past the clamp limits)
- combo: use clipper.
- combo: a way/helper to customize the combo preview (#1658) -> experimental BeginComboPreview()
- combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203)
- listbox: multiple selection (WIP range-select branch)
@@ -201,13 +200,14 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- tooltip: drag and drop with tooltip near monitor edges lose/changes its last direction instead of locking one. The drag and drop tooltip should always follow without changing direction.
- tooltip: allow to set the width of a tooltip to allow TextWrapped() etc. while keeping the height automatic.
- tooltip: drag tooltip hovering over source widget with IsItemHovered/SetTooltip flickers (WIP branch)
- tooltip: tooltip priorities to override a stock tooltip (e.g. shortcut tooltip)
- status-bar: add a per-window status bar helper similar to what menu-bar does. generalize concept of layer0 rect in window (can make _MenuBar window flag obsolete too).
- shortcuts: store multiple keychords in ImGuiKeyChord
- shortcuts: Hovered route (lower than Focused, higher than Global)
- shortcuts: local-style shortcut api, e.g. parse "&Save"
- shortcuts,menus: global-style shortcut api e.g. "Save (CTRL+S)" -> explicit flag for recursing into closed menu
- shortcuts: programmatically access shortcuts "Focus("&Save"))
- menus: menu-bar: main menu-bar could affect clamping of windows position (~ akin to modifying DisplayMin)
- menus: hovering from menu to menu on a menu-bar has 1 frame without any menu, which is a little annoying. ideally either 0 either longer.
- menus: hovering from menu to menu on a menu-bar has 1 frame without any menu, which is a little annoying. ideally zero.
- menus: would be nice if the Selectable() supported horizontal alignment (must be given the equivalent of WorkRect.Max.x matching the position of the shortcut column)
- tree node: add treenode/treepush int variants? not there because (void*) cast from int warns on some platforms/settings?
@@ -303,7 +303,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- font/opt: Considering storing standalone AdvanceX table as 16-bit fixed point integer?
- font/opt: Glyph currently 40 bytes (2+9*4). Consider storing UV as 16-bits integer? (->32 bytes). X0/Y0/X1/Y1 as 16 fixed-point integers? Or X0/Y0 as float and X1/Y1 as fixed8_8?
- nav: visual feedback on button press.
- nav: some features such as PageUp/Down/Home/End should probably work without ImGuiConfigFlags_NavEnableKeyboard? (where do we draw the line? how about CTRL+Tab)
! nav: never clear NavId on some setup (e.g. gamepad centric)
- nav: there's currently no way to completely clear focus with the keyboard. depending on patterns used by the application to dispatch inputs, it may be desirable.
@@ -357,8 +356,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- misc: make the ImGuiCond values linear (non-power-of-two). internal storage for ImGuiWindow can use integers to combine into flags (Why?)
- misc: PushItemFlag(): add a flag to disable keyboard capture when used with mouse? (#1682)
- misc: use more size_t in public api?
- misc: possible compile-time support for string view/range instead of char* would e.g. facilitate usage with Rust (#683, #3038, WIP string_view branch)
- misc: possible compile-time support for wchar_t instead of char*?
- misc: support for string view/range instead of char* would e.g. facilitate usage with Rust (#683, #3038, WIP string_view branch)
- demo: demonstrate using PushStyleVar() in more details.
- demo: add vertical separator demo
@@ -378,7 +376,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- backends: bgfx: https://gist.github.com/RichardGale/6e2b74bc42b3005e08397236e4be0fd0
- backends: emscriptem: with refactored examples, we could provide a direct imgui_impl_emscripten platform layer (see eg. https://github.com/floooh/sokol-samples/blob/master/html5/imgui-emsc.cc#L42)
- bindings: ways to use clang ast dump to generate bindings or helpers for bindings? (e.g. clang++ -Xclang -ast-dump=json imgui.h) (WIP project "dear-bindings" still private)
- bindings: ways to use clang ast dump to generate bindings or helpers for bindings? (e.g. clang++ -Xclang -ast-dump=json imgui.h) (--> use https://github.com/dearimgui/dear_bindings)
- optimization: replace vsnprintf with stb_printf? using IMGUI_USE_STB_SPRINTF. (#1038 + needed for string_view)
- optimization: add clipping for multi-component widgets (SliderFloatX, ColorEditX, etc.). one problem is that nav branch can't easily clip parent group when there is a move request.

View File

@@ -161,7 +161,7 @@ void Init(struct android_app* app)
// We load the default font with increased size to improve readability on many devices with "high" DPI.
// FIXME: Put some effort into DPI awareness.
// Important: when calling AddFontFromMemoryTTF(), ownership of font_data is transfered by Dear ImGui by default (deleted is handled by Dear ImGui), unless we set FontDataOwnedByAtlas=false in ImFontConfig
// Important: when calling AddFontFromMemoryTTF(), ownership of font_data is transferred by Dear ImGui by default (deleted is handled by Dear ImGui), unless we set FontDataOwnedByAtlas=false in ImFontConfig
ImFontConfig font_cfg;
font_cfg.SizePixels = 22.0f;
io.Fonts->AddFontDefault(&font_cfg);

View File

@@ -1,253 +0,0 @@
// Dear ImGui: standalone example application for Emscripten, using GLFW + WebGPU
// (Emscripten is a C++-to-javascript compiler, used to publish executables for the web. See https://emscripten.org/)
// 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_glfw.h"
#include "imgui_impl_wgpu.h"
#include <stdio.h>
#include <emscripten.h>
#include <emscripten/html5.h>
#include <emscripten/html5_webgpu.h>
#include <GLFW/glfw3.h>
#include <webgpu/webgpu.h>
#include <webgpu/webgpu_cpp.h>
// Global WebGPU required states
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_swap_chain_width = 0;
static int wgpu_swap_chain_height = 0;
// Forward declarations
static void MainLoopStep(void* window);
static bool InitWGPU();
static void print_glfw_error(int error, const char* description);
static void print_wgpu_error(WGPUErrorType error_type, const char* message, void*);
// Main code
int main(int, char**)
{
glfwSetErrorCallback(print_glfw_error);
if (!glfwInit())
return 1;
// Make sure GLFW does not initialize any graphics context.
// This needs to be done explicitly later.
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr);
if (!window)
{
glfwTerminate();
return 1;
}
// Initialize the WebGPU environment
if (!InitWGPU())
{
if (window)
glfwDestroyWindow(window);
glfwTerminate();
return 1;
}
glfwShowWindow(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
// 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;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
// Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForOther(window, true);
ImGui_ImplWGPU_Init(wgpu_device, 3, wgpu_preferred_fmt, WGPUTextureFormat_Undefined);
// 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).
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
// - 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.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
// - Emscripten allows preloading a file or folder to be accessible at runtime. See Makefile for details.
//io.Fonts->AddFontDefault();
#ifndef IMGUI_DISABLE_FILE_FUNCTIONS
//io.Fonts->AddFontFromFileTTF("fonts/segoeui.ttf", 18.0f);
io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("fonts/ProggyTiny.ttf", 10.0f);
//ImFont* font = io.Fonts->AddFontFromFileTTF("fonts/ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != nullptr);
#endif
// This function will directly return and exit the main function.
// Make sure that no required objects get cleaned up.
// This way we can use the browsers 'requestAnimationFrame' to control the rendering.
emscripten_set_main_loop_arg(MainLoopStep, window, 0, false);
return 0;
}
static bool InitWGPU()
{
wgpu_device = emscripten_webgpu_get_device();
if (!wgpu_device)
return false;
wgpuDeviceSetUncapturedErrorCallback(wgpu_device, print_wgpu_error, nullptr);
// Use C++ wrapper due to misbehavior in Emscripten.
// Some offset computation for wgpuInstanceCreateSurface in JavaScript
// seem to be inline with struct alignments in the C++ structure
wgpu::SurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
html_surface_desc.selector = "#canvas";
wgpu::SurfaceDescriptor surface_desc = {};
surface_desc.nextInChain = &html_surface_desc;
wgpu::Instance instance = wgpuCreateInstance(nullptr);
wgpu::Surface surface = instance.CreateSurface(&surface_desc);
wgpu::Adapter adapter = {};
wgpu_preferred_fmt = (WGPUTextureFormat)surface.GetPreferredFormat(adapter);
wgpu_surface = surface.Release();
return true;
}
static void MainLoopStep(void* window)
{
ImGuiIO& io = ImGui::GetIO();
glfwPollEvents();
int width, height;
glfwGetFramebufferSize((GLFWwindow*)window, &width, &height);
// React to changes in screen size
if (width != wgpu_swap_chain_width && height != wgpu_swap_chain_height)
{
ImGui_ImplWGPU_InvalidateDeviceObjects();
if (wgpu_swap_chain)
wgpuSwapChainRelease(wgpu_swap_chain);
wgpu_swap_chain_width = width;
wgpu_swap_chain_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_CreateDeviceObjects();
}
// Start the Dear ImGui frame
ImGui_ImplWGPU_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// Our state
// (we use static, which essentially makes the variable globals, as a convenience to keep the example code easy to follow)
static bool show_demo_window = true;
static bool show_another_window = false;
static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// 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();
WGPURenderPassColorAttachment color_attachments = {};
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);
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);
WGPUQueue queue = wgpuDeviceGetQueue(wgpu_device);
wgpuQueueSubmit(queue, 1, &cmd_buffer);
}
static void print_glfw_error(int error, const char* description)
{
printf("GLFW Error %d: %s\n", error, description);
}
static void print_wgpu_error(WGPUErrorType error_type, const char* message, void*)
{
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);
}

View File

@@ -14,10 +14,10 @@ SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
LIBS = -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -framework CoreVideo -framework QuartzCore
LIBS += -L/usr/local/lib -L/opt/homebrew/lib
LIBS += -L/usr/local/lib -L/opt/homebrew/lib -L/opt/local/lib
LIBS += -lglfw
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I/usr/local/include -I/opt/homebrew/include
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I/usr/local/include -I/opt/homebrew/include -I/opt/local/include
CXXFLAGS += -Wall -Wformat
CFLAGS = $(CXXFLAGS)

View File

@@ -59,7 +59,7 @@ endif
CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
#CPPFLAGS += -g
CPPFLAGS += -Wall -Wformat -Os $(EMS)
# LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html
LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html
LDFLAGS += $(EMS)
##---------------------------------------------------------------------

View File

@@ -96,6 +96,9 @@ int main(int, char**)
// Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForOpenGL(window, true);
#ifdef __EMSCRIPTEN__
ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback("#canvas");
#endif
ImGui_ImplOpenGL3_Init(glsl_version);
// Load Fonts

View File

@@ -21,8 +21,12 @@
#define GLFW_INCLUDE_NONE
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#include <vulkan/vulkan.h>
//#include <vulkan/vulkan_beta.h>
// Volk headers
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
#define VOLK_IMPLEMENTATION
#include <Volk/volk.h>
#endif
// [Win32] Our example includes a copy of glfw3.lib pre-compiled with VS2010 to maximize ease of testing and compatibility with old VS compilers.
// To link with VS2010-era libraries, VS2015+ requires linking with legacy_stdio_definitions.lib, which we do using this pragma.
@@ -31,9 +35,9 @@
#pragma comment(lib, "legacy_stdio_definitions")
#endif
//#define IMGUI_UNLIMITED_FRAME_RATE
//#define APP_USE_UNLIMITED_FRAME_RATE
#ifdef _DEBUG
#define IMGUI_VULKAN_DEBUG_REPORT
#define APP_USE_VULKAN_DEBUG_REPORT
#endif
// Data
@@ -64,14 +68,14 @@ static void check_vk_result(VkResult err)
abort();
}
#ifdef IMGUI_VULKAN_DEBUG_REPORT
#ifdef APP_USE_VULKAN_DEBUG_REPORT
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
{
(void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments
fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
return VK_FALSE;
}
#endif // IMGUI_VULKAN_DEBUG_REPORT
#endif // APP_USE_VULKAN_DEBUG_REPORT
static bool IsExtensionAvailable(const ImVector<VkExtensionProperties>& properties, const char* extension)
{
@@ -113,6 +117,9 @@ static VkPhysicalDevice SetupVulkan_SelectPhysicalDevice()
static void SetupVulkan(ImVector<const char*> instance_extensions)
{
VkResult err;
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
volkInitialize();
#endif
// Create Vulkan Instance
{
@@ -139,7 +146,7 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
#endif
// Enabling validation layers
#ifdef IMGUI_VULKAN_DEBUG_REPORT
#ifdef APP_USE_VULKAN_DEBUG_REPORT
const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
create_info.enabledLayerCount = 1;
create_info.ppEnabledLayerNames = layers;
@@ -151,17 +158,20 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
create_info.ppEnabledExtensionNames = instance_extensions.Data;
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
check_vk_result(err);
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
volkLoadInstance(g_Instance);
#endif
// Setup the debug report callback
#ifdef IMGUI_VULKAN_DEBUG_REPORT
auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
IM_ASSERT(vkCreateDebugReportCallbackEXT != nullptr);
#ifdef APP_USE_VULKAN_DEBUG_REPORT
auto f_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
IM_ASSERT(f_vkCreateDebugReportCallbackEXT != nullptr);
VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
debug_report_ci.pfnCallback = debug_report;
debug_report_ci.pUserData = nullptr;
err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
err = f_vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
check_vk_result(err);
#endif
}
@@ -258,7 +268,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
// Select Present Mode
#ifdef IMGUI_UNLIMITED_FRAME_RATE
#ifdef APP_USE_UNLIMITED_FRAME_RATE
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR };
#else
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR };
@@ -275,11 +285,11 @@ static void CleanupVulkan()
{
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
#ifdef IMGUI_VULKAN_DEBUG_REPORT
#ifdef APP_USE_VULKAN_DEBUG_REPORT
// Remove the debug report callback
auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
#endif // IMGUI_VULKAN_DEBUG_REPORT
auto f_vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
f_vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
#endif // APP_USE_VULKAN_DEBUG_REPORT
vkDestroyDevice(g_Device, g_Allocator);
vkDestroyInstance(g_Instance, g_Allocator);
@@ -376,7 +386,7 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd)
return;
}
check_vk_result(err);
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores
}
// Main code
@@ -446,13 +456,14 @@ int main(int, char**)
init_info.Queue = g_Queue;
init_info.PipelineCache = g_PipelineCache;
init_info.DescriptorPool = g_DescriptorPool;
init_info.RenderPass = wd->RenderPass;
init_info.Subpass = 0;
init_info.MinImageCount = g_MinImageCount;
init_info.ImageCount = wd->ImageCount;
init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
init_info.Allocator = g_Allocator;
init_info.CheckVkResultFn = check_vk_result;
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
ImGui_ImplVulkan_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.

View File

@@ -0,0 +1,100 @@
# 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_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
# 3. cmake --build build
# 4. emrun build/index.html
cmake_minimum_required(VERSION 3.10.2)
project(imgui_example_glfw_wgpu C CXX)
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 ../../)
# Libraries
if(EMSCRIPTEN)
set(LIBRARIES glfw)
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
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)
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
)
target_include_directories(example_glfw_wgpu PUBLIC
${IMGUI_DIR}
${IMGUI_DIR}/backends
)
target_link_libraries(example_glfw_wgpu PUBLIC ${LIBRARIES})
# Emscripten settings
if(EMSCRIPTEN)
target_link_options(example_glfw_wgpu PRIVATE
"-sUSE_WEBGPU=1"
"-sUSE_GLFW=3"
"-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>
)
endif()

View File

@@ -6,7 +6,7 @@
- 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` while in the `example_emscripten_wgpu/` directory.
- 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.
@@ -18,7 +18,7 @@ To run on a local machine:
- 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_emscripten_opengl3.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.
- 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,346 @@
// Dear ImGui: standalone example application for using GLFW + 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_glfw.h"
#include "imgui_impl_wgpu.h"
#include <stdio.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <emscripten/html5.h>
#include <emscripten/html5_webgpu.h>
#else
#include <webgpu/webgpu_glfw.h>
#endif
#include <GLFW/glfw3.h>
#include <webgpu/webgpu.h>
#include <webgpu/webgpu_cpp.h>
// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details.
#ifdef __EMSCRIPTEN__
#include "../libs/emscripten/emscripten_mainloop_stub.h"
#endif
// Global WebGPU required states
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_swap_chain_width = 1280;
static int wgpu_swap_chain_height = 720;
// Forward declarations
static bool InitWGPU(GLFWwindow* window);
static void CreateSwapChain(int width, int height);
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*)
{
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);
}
// Main code
int main(int, char**)
{
glfwSetErrorCallback(glfw_error_callback);
if (!glfwInit())
return 1;
// Make sure GLFW does not initialize any graphics context.
// This needs to be done explicitly later.
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(wgpu_swap_chain_width, wgpu_swap_chain_height, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr);
if (window == nullptr)
return 1;
// Initialize the WebGPU environment
if (!InitWGPU(window))
{
if (window)
glfwDestroyWindow(window);
glfwTerminate();
return 1;
}
CreateSwapChain(wgpu_swap_chain_width, wgpu_swap_chain_height);
glfwShowWindow(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
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
// Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForOther(window, true);
#ifdef __EMSCRIPTEN__
ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback("#canvas");
#endif
ImGui_ImplWGPU_InitInfo init_info;
init_info.Device = wgpu_device;
init_info.NumFramesInFlight = 3;
init_info.RenderTargetFormat = wgpu_preferred_fmt;
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).
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
// - 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.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
// - Emscripten allows preloading a file or folder to be accessible at runtime. See Makefile for details.
//io.Fonts->AddFontDefault();
#ifndef IMGUI_DISABLE_FILE_FUNCTIONS
//io.Fonts->AddFontFromFileTTF("fonts/segoeui.ttf", 18.0f);
//io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("fonts/ProggyTiny.ttf", 10.0f);
//ImFont* font = io.Fonts->AddFontFromFileTTF("fonts/ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
//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
#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 (!glfwWindowShouldClose(window))
#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.
glfwPollEvents();
// React to changes in screen size
int width, height;
glfwGetFramebufferSize((GLFWwindow*)window, &width, &height);
if (width != wgpu_swap_chain_width || height != wgpu_swap_chain_height)
{
ImGui_ImplWGPU_InvalidateDeviceObjects();
CreateSwapChain(width, height);
ImGui_ImplWGPU_CreateDeviceObjects();
}
// Start the Dear ImGui frame
ImGui_ImplWGPU_NewFrame();
ImGui_ImplGlfw_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();
#ifndef __EMSCRIPTEN__
// Tick needs to be called in Dawn to display validation errors
wgpuDeviceTick(wgpu_device);
#endif
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);
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);
WGPUQueue queue = wgpuDeviceGetQueue(wgpu_device);
wgpuQueueSubmit(queue, 1, &cmd_buffer);
#ifndef __EMSCRIPTEN__
wgpuSwapChainPresent(wgpu_swap_chain);
#endif
wgpuTextureViewRelease(color_attachments.view);
wgpuRenderPassEncoderRelease(pass);
wgpuCommandEncoderRelease(encoder);
wgpuCommandBufferRelease(cmd_buffer);
}
#ifdef __EMSCRIPTEN__
EMSCRIPTEN_MAINLOOP_END;
#endif
// Cleanup
ImGui_ImplWGPU_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
#ifndef __EMSCRIPTEN__
static WGPUAdapter RequestAdapter(WGPUInstance instance)
{
auto onAdapterRequestEnded = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, const char* message, void* pUserData)
{
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;
}
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;
}
#endif
static bool InitWGPU(GLFWwindow* window)
{
wgpu::Instance instance = wgpuCreateInstance(nullptr);
#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
#ifdef __EMSCRIPTEN__
wgpu::SurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
html_surface_desc.selector = "#canvas";
wgpu::SurfaceDescriptor surface_desc = {};
surface_desc.nextInChain = &html_surface_desc;
wgpu::Surface surface = instance.CreateSurface(&surface_desc);
wgpu::Adapter adapter = {};
wgpu_preferred_fmt = (WGPUTextureFormat)surface.GetPreferredFormat(adapter);
#else
wgpu::Surface surface = wgpu::glfw::CreateSurfaceForWindow(instance, window);
if (!surface)
return false;
wgpu_preferred_fmt = WGPUTextureFormat_BGRA8Unorm;
#endif
wgpu_instance = instance.MoveToCHandle();
wgpu_surface = surface.MoveToCHandle();
wgpuDeviceSetUncapturedErrorCallback(wgpu_device, wgpu_error_callback, nullptr);
return true;
}
static void CreateSwapChain(int width, int height)
{
if (wgpu_swap_chain)
wgpuSwapChainRelease(wgpu_swap_chain);
wgpu_swap_chain_width = width;
wgpu_swap_chain_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);
}

View File

@@ -3,7 +3,7 @@
<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+WebGPU example</title>
<title>Dear ImGui Emscripten+GLFW+WebGPU example</title>
<style>
body { margin: 0; background-color: black }
.emscripten {
@@ -63,6 +63,10 @@
// 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;

View File

@@ -47,6 +47,12 @@ int main(int, char**)
// Setup window
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+DirectX11 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
}
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWindowWMInfo(window, &wmInfo);

View File

@@ -41,6 +41,12 @@ int main(int, char**)
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
}
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, gl_context);
SDL_GL_SetSwapInterval(1); // Enable vsync

View File

@@ -68,6 +68,12 @@ int main(int, char**)
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
}
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, gl_context);
SDL_GL_SetSwapInterval(1); // Enable vsync

View File

@@ -38,6 +38,11 @@ int main(int, char**)
// Create window with SDL_Renderer graphics context
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+SDL_Renderer example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
}
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
if (renderer == nullptr)
{
@@ -54,6 +59,7 @@ int main(int, char**)
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
// Setup Dear ImGui style
ImGui::StyleColorsDark();
@@ -150,7 +156,7 @@ int main(int, char**)
SDL_RenderSetScale(renderer, io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
SDL_SetRenderDrawColor(renderer, (Uint8)(clear_color.x * 255), (Uint8)(clear_color.y * 255), (Uint8)(clear_color.z * 255), (Uint8)(clear_color.w * 255));
SDL_RenderClear(renderer);
ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData());
ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData(), renderer);
SDL_RenderPresent(renderer);
}

View File

@@ -20,12 +20,16 @@
#include <stdlib.h> // abort
#include <SDL.h>
#include <SDL_vulkan.h>
#include <vulkan/vulkan.h>
//#include <vulkan/vulkan_beta.h>
//#define IMGUI_UNLIMITED_FRAME_RATE
// Volk headers
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
#define VOLK_IMPLEMENTATION
#include <Volk/volk.h>
#endif
//#define APP_USE_UNLIMITED_FRAME_RATE
#ifdef _DEBUG
#define IMGUI_VULKAN_DEBUG_REPORT
#define APP_USE_VULKAN_DEBUG_REPORT
#endif
// Data
@@ -52,14 +56,14 @@ static void check_vk_result(VkResult err)
abort();
}
#ifdef IMGUI_VULKAN_DEBUG_REPORT
#ifdef APP_USE_VULKAN_DEBUG_REPORT
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
{
(void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments
fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
return VK_FALSE;
}
#endif // IMGUI_VULKAN_DEBUG_REPORT
#endif // APP_USE_VULKAN_DEBUG_REPORT
static bool IsExtensionAvailable(const ImVector<VkExtensionProperties>& properties, const char* extension)
{
@@ -101,6 +105,9 @@ static VkPhysicalDevice SetupVulkan_SelectPhysicalDevice()
static void SetupVulkan(ImVector<const char*> instance_extensions)
{
VkResult err;
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
volkInitialize();
#endif
// Create Vulkan Instance
{
@@ -127,7 +134,7 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
#endif
// Enabling validation layers
#ifdef IMGUI_VULKAN_DEBUG_REPORT
#ifdef APP_USE_VULKAN_DEBUG_REPORT
const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
create_info.enabledLayerCount = 1;
create_info.ppEnabledLayerNames = layers;
@@ -139,17 +146,20 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
create_info.ppEnabledExtensionNames = instance_extensions.Data;
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
check_vk_result(err);
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
volkLoadInstance(g_Instance);
#endif
// Setup the debug report callback
#ifdef IMGUI_VULKAN_DEBUG_REPORT
auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
IM_ASSERT(vkCreateDebugReportCallbackEXT != nullptr);
#ifdef APP_USE_VULKAN_DEBUG_REPORT
auto f_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
IM_ASSERT(f_vkCreateDebugReportCallbackEXT != nullptr);
VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
debug_report_ci.pfnCallback = debug_report;
debug_report_ci.pUserData = nullptr;
err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
err = f_vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
check_vk_result(err);
#endif
}
@@ -246,7 +256,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
// Select Present Mode
#ifdef IMGUI_UNLIMITED_FRAME_RATE
#ifdef APP_UNLIMITED_FRAME_RATE
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR };
#else
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR };
@@ -263,11 +273,11 @@ static void CleanupVulkan()
{
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
#ifdef IMGUI_VULKAN_DEBUG_REPORT
#ifdef APP_USE_VULKAN_DEBUG_REPORT
// Remove the debug report callback
auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
#endif // IMGUI_VULKAN_DEBUG_REPORT
auto f_vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
f_vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
#endif // APP_USE_VULKAN_DEBUG_REPORT
vkDestroyDevice(g_Device, g_Allocator);
vkDestroyInstance(g_Instance, g_Allocator);
@@ -364,7 +374,7 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd)
return;
}
check_vk_result(err);
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores
}
// Main code
@@ -385,6 +395,11 @@ int main(int, char**)
// Create window with Vulkan graphics context
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+Vulkan example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
}
ImVector<const char*> extensions;
uint32_t extensions_count = 0;
@@ -441,13 +456,14 @@ int main(int, char**)
init_info.Queue = g_Queue;
init_info.PipelineCache = g_PipelineCache;
init_info.DescriptorPool = g_DescriptorPool;
init_info.RenderPass = wd->RenderPass;
init_info.Subpass = 0;
init_info.MinImageCount = g_MinImageCount;
init_info.ImageCount = wd->ImageCount;
init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
init_info.Allocator = g_Allocator;
init_info.CheckVkResultFn = check_vk_result;
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
ImGui_ImplVulkan_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.

View File

@@ -37,9 +37,9 @@ LIBS =
ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
LIBS += $(LINUX_GL_LIBS) -ldl `sdl3-config --libs`
LIBS += $(LINUX_GL_LIBS) -ldl `pkg-config sdl3 --libs`
CXXFLAGS += `sdl3-config --cflags`
CXXFLAGS += `pkg-config sdl3 --cflags`
CFLAGS = $(CXXFLAGS)
endif
@@ -48,7 +48,7 @@ ifeq ($(UNAME_S), Darwin) #APPLE
LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl3-config --libs`
LIBS += -L/usr/local/lib -L/opt/local/lib
CXXFLAGS += `sdl3-config --cflags`
CXXFLAGS += `pkg-config sdl3 --cflags`
CXXFLAGS += -I/usr/local/include -I/opt/local/include
CFLAGS = $(CXXFLAGS)
endif

View File

@@ -64,7 +64,7 @@ int main(int, char**)
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN);
Uint32 window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN;
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+OpenGL3 example", 1280, 720, window_flags);
if (window == nullptr)
{

View File

@@ -26,9 +26,9 @@ LIBS =
ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
LIBS += -ldl `sdl3-config --libs`
LIBS += -ldl `pkg-config sdl3 --libs`
CXXFLAGS += `sdl3-config --cflags`
CXXFLAGS += `pkg-config sdl3 --cflags`
CFLAGS = $(CXXFLAGS)
endif
@@ -37,7 +37,7 @@ ifeq ($(UNAME_S), Darwin) #APPLE
LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl3-config --libs`
LIBS += -L/usr/local/lib -L/opt/local/lib
CXXFLAGS += `sdl3-config --cflags`
CXXFLAGS += `pkg-config sdl3 --cflags`
CXXFLAGS += -I/usr/local/include -I/opt/local/include
CFLAGS = $(CXXFLAGS)
endif

View File

@@ -35,19 +35,20 @@ int main(int, char**)
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
// Create window with SDL_Renderer graphics context
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN);
Uint32 window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN;
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+SDL_Renderer example", 1280, 720, window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
}
SDL_Renderer* renderer = SDL_CreateRenderer(window, NULL, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
SDL_Renderer* renderer = SDL_CreateRenderer(window, nullptr);
SDL_SetRenderVSync(renderer, 1);
if (renderer == nullptr)
{
SDL_Log("Error: SDL_CreateRenderer(): %s\n", SDL_GetError());
return -1;
}
}
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_ShowWindow(window);
@@ -57,6 +58,7 @@ int main(int, char**)
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
// Setup Dear ImGui style
ImGui::StyleColorsDark();
@@ -159,9 +161,9 @@ int main(int, char**)
// Rendering
ImGui::Render();
//SDL_RenderSetScale(renderer, io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
SDL_SetRenderDrawColor(renderer, (Uint8)(clear_color.x * 255), (Uint8)(clear_color.y * 255), (Uint8)(clear_color.z * 255), (Uint8)(clear_color.w * 255));
SDL_SetRenderDrawColorFloat(renderer, clear_color.x, clear_color.y, clear_color.z, clear_color.w);
SDL_RenderClear(renderer);
ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData());
ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), renderer);
SDL_RenderPresent(renderer);
}

View File

@@ -16,6 +16,7 @@
// Data
static ID3D10Device* g_pd3dDevice = nullptr;
static IDXGISwapChain* g_pSwapChain = nullptr;
static bool g_SwapChainOccluded = false;
static UINT g_ResizeWidth = 0, g_ResizeHeight = 0;
static ID3D10RenderTargetView* g_mainRenderTargetView = nullptr;
@@ -112,6 +113,14 @@ int main(int, char**)
if (done)
break;
// Handle window being minimized or screen locked
if (g_SwapChainOccluded && g_pSwapChain->Present(0, DXGI_PRESENT_TEST) == DXGI_STATUS_OCCLUDED)
{
::Sleep(10);
continue;
}
g_SwapChainOccluded = false;
// Handle window resize (we don't resize directly in the WM_SIZE handler)
if (g_ResizeWidth != 0 && g_ResizeHeight != 0)
{
@@ -177,10 +186,13 @@ int main(int, char**)
ImGui::RenderPlatformWindowsDefault();
}
g_pSwapChain->Present(1, 0); // Present with vsync
//g_pSwapChain->Present(0, 0); // Present without vsync
// Present
HRESULT hr = g_pSwapChain->Present(1, 0); // Present with vsync
//HRESULT hr = g_pSwapChain->Present(0, 0); // Present without vsync
g_SwapChainOccluded = (hr == DXGI_STATUS_OCCLUDED);
}
// Cleanup
ImGui_ImplDX10_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();

View File

@@ -16,6 +16,7 @@
static ID3D11Device* g_pd3dDevice = nullptr;
static ID3D11DeviceContext* g_pd3dDeviceContext = nullptr;
static IDXGISwapChain* g_pSwapChain = nullptr;
static bool g_SwapChainOccluded = false;
static UINT g_ResizeWidth = 0, g_ResizeHeight = 0;
static ID3D11RenderTargetView* g_mainRenderTargetView = nullptr;
@@ -117,6 +118,14 @@ int main(int, char**)
if (done)
break;
// Handle window being minimized or screen locked
if (g_SwapChainOccluded && g_pSwapChain->Present(0, DXGI_PRESENT_TEST) == DXGI_STATUS_OCCLUDED)
{
::Sleep(10);
continue;
}
g_SwapChainOccluded = false;
// Handle window resize (we don't resize directly in the WM_SIZE handler)
if (g_ResizeWidth != 0 && g_ResizeHeight != 0)
{
@@ -182,8 +191,10 @@ int main(int, char**)
ImGui::RenderPlatformWindowsDefault();
}
g_pSwapChain->Present(1, 0); // Present with vsync
//g_pSwapChain->Present(0, 0); // Present without vsync
// Present
HRESULT hr = g_pSwapChain->Present(1, 0); // Present with vsync
//HRESULT hr = g_pSwapChain->Present(0, 0); // Present without vsync
g_SwapChainOccluded = (hr == DXGI_STATUS_OCCLUDED);
}
// Cleanup

View File

@@ -26,6 +26,8 @@
#pragma comment(lib, "dxguid.lib")
#endif
#include "imgui_internal.h"
struct FrameContext
{
ID3D12CommandAllocator* CommandAllocator;
@@ -47,6 +49,7 @@ static ID3D12Fence* g_fence = nullptr;
static HANDLE g_fenceEvent = nullptr;
static UINT64 g_fenceLastSignaledValue = 0;
static IDXGISwapChain3* g_pSwapChain = nullptr;
static bool g_SwapChainOccluded = false;
static HANDLE g_hSwapChainWaitableObject = nullptr;
static ID3D12Resource* g_mainRenderTargetResource[NUM_BACK_BUFFERS] = {};
static D3D12_CPU_DESCRIPTOR_HANDLE g_mainRenderTargetDescriptor[NUM_BACK_BUFFERS] = {};
@@ -149,6 +152,14 @@ int main(int, char**)
if (done)
break;
// Handle window screen locked
if (g_SwapChainOccluded && g_pSwapChain->Present(0, DXGI_PRESENT_TEST) == DXGI_STATUS_OCCLUDED)
{
::Sleep(10);
continue;
}
g_SwapChainOccluded = false;
// Start the Dear ImGui frame
ImGui_ImplDX12_NewFrame();
ImGui_ImplWin32_NewFrame();
@@ -228,8 +239,10 @@ int main(int, char**)
ImGui::RenderPlatformWindowsDefault(nullptr, (void*)g_pd3dCommandList);
}
g_pSwapChain->Present(1, 0); // Present with vsync
//g_pSwapChain->Present(0, 0); // Present without vsync
// Present
HRESULT hr = g_pSwapChain->Present(1, 0); // Present with vsync
//HRESULT hr = g_pSwapChain->Present(0, 0); // Present without vsync
g_SwapChainOccluded = (hr == DXGI_STATUS_OCCLUDED);
UINT64 fenceValue = g_fenceLastSignaledValue + 1;
g_pd3dCommandQueue->Signal(g_fence, fenceValue);

View File

@@ -15,6 +15,7 @@
// Data
static LPDIRECT3D9 g_pD3D = nullptr;
static LPDIRECT3DDEVICE9 g_pd3dDevice = nullptr;
static bool g_DeviceLost = false;
static UINT g_ResizeWidth = 0, g_ResizeHeight = 0;
static D3DPRESENT_PARAMETERS g_d3dpp = {};
@@ -110,6 +111,20 @@ int main(int, char**)
if (done)
break;
// Handle lost D3D9 device
if (g_DeviceLost)
{
HRESULT hr = g_pd3dDevice->TestCooperativeLevel();
if (hr == D3DERR_DEVICELOST)
{
::Sleep(10);
continue;
}
if (hr == D3DERR_DEVICENOTRESET)
ResetDevice();
g_DeviceLost = false;
}
// Handle window resize (we don't resize directly in the WM_SIZE handler)
if (g_ResizeWidth != 0 && g_ResizeHeight != 0)
{
@@ -183,12 +198,11 @@ int main(int, char**)
}
HRESULT result = g_pd3dDevice->Present(nullptr, nullptr, nullptr, nullptr);
// Handle loss of D3D9 device
if (result == D3DERR_DEVICELOST && g_pd3dDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET)
ResetDevice();
if (result == D3DERR_DEVICELOST)
g_DeviceLost = true;
}
// Cleanup
ImGui_ImplDX9_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();

View File

@@ -74,9 +74,9 @@ int main(int, char**)
{
// Create application window
//ImGui_ImplWin32_EnableDpiAwareness();
WNDCLASSEXW wc = { sizeof(wc), CS_OWNDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, L"ImGui Example", NULL };
WNDCLASSEXW wc = { sizeof(wc), CS_OWNDC, WndProc, 0L, 0L, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, L"ImGui Example", nullptr };
::RegisterClassExW(&wc);
HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Dear ImGui Win32+OpenGL3 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Dear ImGui Win32+OpenGL3 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, nullptr, nullptr, wc.hInstance, nullptr);
// Initialize OpenGL
if (!CreateDeviceWGL(hwnd, &g_MainWindow))
@@ -134,7 +134,7 @@ int main(int, char**)
// 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 NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - 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).
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
// - 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.
@@ -144,8 +144,8 @@ int main(int, char**)
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != nullptr);
// Our state
bool show_demo_window = true;
@@ -159,7 +159,7 @@ int main(int, char**)
// Poll and handle messages (inputs, window resize, etc.)
// See the WndProc() function below for our to dispatch events to the Win32 backend.
MSG msg;
while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
@@ -270,7 +270,7 @@ bool CreateDeviceWGL(HWND hWnd, WGL_WindowData* data)
void CleanupDeviceWGL(HWND hWnd, WGL_WindowData* data)
{
wglMakeCurrent(NULL, NULL);
wglMakeCurrent(nullptr, nullptr);
::ReleaseDC(hWnd, data->hDC);
}

View File

@@ -200,7 +200,7 @@ typedef void (*uSynergySleepFunc)(uSynergyCookie cookie, int timeMs);
@brief Get time function
This function is called when uSynergy needs to know the current time. This is used to determine when timeouts
have occured. The time base should be a cyclic millisecond time value.
have occurred. The time base should be a cyclic millisecond time value.
@returns Time value in milliseconds
**/

View File

@@ -50,12 +50,14 @@
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
//---- Include imgui_user.h at the end of imgui.h as a convenience
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
//#define IMGUI_INCLUDE_IMGUI_USER_H
//#define IMGUI_USER_H_FILENAME "my_folder/my_imgui_user.h"
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
//#define IMGUI_USE_BGRA_PACKED_COLOR
//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
//---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
//#define IMGUI_USE_WCHAR32
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version

2568
imgui.cpp

File diff suppressed because it is too large Load Diff

1523
imgui.h

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.90.0
// dear imgui, v1.90.8
// (drawing and font code)
/*
@@ -8,6 +8,7 @@ Index of this file:
// [SECTION] STB libraries implementation
// [SECTION] Style functions
// [SECTION] ImDrawList
// [SECTION] ImTriangulator, ImDrawList concave polygon fill
// [SECTION] ImDrawListSplitter
// [SECTION] ImDrawData
// [SECTION] Helpers ShadeVertsXXX functions
@@ -64,6 +65,7 @@ Index of this file:
#pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double.
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
#pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access
#elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
@@ -389,6 +391,7 @@ void ImDrawListSharedData::SetCircleTessellationMaxError(float max_error)
}
// Initialize before use in a new frame. We always have a command ready in the buffer.
// In the majority of cases, you would want to call PushClipRect() and PushTextureID() after this.
void ImDrawList::_ResetForNewFrame()
{
// Verify that the ImDrawCmd fields we want to memcmp() are contiguous in memory.
@@ -647,7 +650,7 @@ void ImDrawList::PrimReserve(int idx_count, int vtx_count)
_IdxWritePtr = IdxBuffer.Data + idx_buffer_old_size;
}
// Release the a number of reserved vertices/indices from the end of the last reservation made with PrimReserve().
// Release the number of reserved vertices/indices from the end of the last reservation made with PrimReserve().
void ImDrawList::PrimUnreserve(int idx_count, int vtx_count)
{
IM_ASSERT_PARANOID(idx_count >= 0 && vtx_count >= 0);
@@ -1223,10 +1226,10 @@ void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, floa
}
}
void ImDrawList::PathEllipticalArcTo(const ImVec2& center, float radius_x, float radius_y, float rot, float a_min, float a_max, int num_segments)
void ImDrawList::PathEllipticalArcTo(const ImVec2& center, const ImVec2& radius, float rot, float a_min, float a_max, int num_segments)
{
if (num_segments <= 0)
num_segments = _CalcCircleAutoSegmentCount(ImMax(radius_x, radius_y)); // A bit pessimistic, maybe there's a better computation to do here.
num_segments = _CalcCircleAutoSegmentCount(ImMax(radius.x, radius.y)); // A bit pessimistic, maybe there's a better computation to do here.
_Path.reserve(_Path.Size + (num_segments + 1));
@@ -1235,11 +1238,10 @@ void ImDrawList::PathEllipticalArcTo(const ImVec2& center, float radius_x, float
for (int i = 0; i <= num_segments; i++)
{
const float a = a_min + ((float)i / (float)num_segments) * (a_max - a_min);
ImVec2 point(ImCos(a) * radius_x, ImSin(a) * radius_y);
const float rel_x = (point.x * cos_rot) - (point.y * sin_rot);
const float rel_y = (point.x * sin_rot) + (point.y * cos_rot);
point.x = rel_x + center.x;
point.y = rel_y + center.y;
ImVec2 point(ImCos(a) * radius.x, ImSin(a) * radius.y);
const ImVec2 rel((point.x * cos_rot) - (point.y * sin_rot), (point.x * sin_rot) + (point.y * cos_rot));
point.x = rel.x + center.x;
point.y = rel.y + center.y;
_Path.push_back(point);
}
}
@@ -1564,31 +1566,31 @@ void ImDrawList::AddNgonFilled(const ImVec2& center, float radius, ImU32 col, in
}
// Ellipse
void ImDrawList::AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot, int num_segments, float thickness)
void ImDrawList::AddEllipse(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot, int num_segments, float thickness)
{
if ((col & IM_COL32_A_MASK) == 0)
return;
if (num_segments <= 0)
num_segments = _CalcCircleAutoSegmentCount(ImMax(radius_x, radius_y)); // A bit pessimistic, maybe there's a better computation to do here.
num_segments = _CalcCircleAutoSegmentCount(ImMax(radius.x, radius.y)); // A bit pessimistic, maybe there's a better computation to do here.
// Because we are filling a closed shape we remove 1 from the count of segments/points
const float a_max = IM_PI * 2.0f * ((float)num_segments - 1.0f) / (float)num_segments;
PathEllipticalArcTo(center, radius_x, radius_y, rot, 0.0f, a_max, num_segments - 1);
PathEllipticalArcTo(center, radius, rot, 0.0f, a_max, num_segments - 1);
PathStroke(col, true, thickness);
}
void ImDrawList::AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot, int num_segments)
void ImDrawList::AddEllipseFilled(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot, int num_segments)
{
if ((col & IM_COL32_A_MASK) == 0)
return;
if (num_segments <= 0)
num_segments = _CalcCircleAutoSegmentCount(ImMax(radius_x, radius_y)); // A bit pessimistic, maybe there's a better computation to do here.
num_segments = _CalcCircleAutoSegmentCount(ImMax(radius.x, radius.y)); // A bit pessimistic, maybe there's a better computation to do here.
// Because we are filling a closed shape we remove 1 from the count of segments/points
const float a_max = IM_PI * 2.0f * ((float)num_segments - 1.0f) / (float)num_segments;
PathEllipticalArcTo(center, radius_x, radius_y, rot, 0.0f, a_max, num_segments - 1);
PathEllipticalArcTo(center, radius, rot, 0.0f, a_max, num_segments - 1);
PathFillConvex(col);
}
@@ -1619,10 +1621,11 @@ void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos,
if ((col & IM_COL32_A_MASK) == 0)
return;
// Accept null ranges
if (text_begin == text_end || text_begin[0] == 0)
return;
if (text_end == NULL)
text_end = text_begin + strlen(text_begin);
if (text_begin == text_end)
return;
// Pull default font/size from the shared ImDrawListSharedData instance
if (font == NULL)
@@ -1706,6 +1709,316 @@ void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_mi
PopTextureID();
}
//-----------------------------------------------------------------------------
// [SECTION] ImTriangulator, ImDrawList concave polygon fill
//-----------------------------------------------------------------------------
// Triangulate concave polygons. Based on "Triangulation by Ear Clipping" paper, O(N^2) complexity.
// Reference: https://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf
// Provided as a convenience for user but not used by main library.
//-----------------------------------------------------------------------------
// - ImTriangulator [Internal]
// - AddConcavePolyFilled()
//-----------------------------------------------------------------------------
enum ImTriangulatorNodeType
{
ImTriangulatorNodeType_Convex,
ImTriangulatorNodeType_Ear,
ImTriangulatorNodeType_Reflex
};
struct ImTriangulatorNode
{
ImTriangulatorNodeType Type;
int Index;
ImVec2 Pos;
ImTriangulatorNode* Next;
ImTriangulatorNode* Prev;
void Unlink() { Next->Prev = Prev; Prev->Next = Next; }
};
struct ImTriangulatorNodeSpan
{
ImTriangulatorNode** Data = NULL;
int Size = 0;
void push_back(ImTriangulatorNode* node) { Data[Size++] = node; }
void find_erase_unsorted(int idx) { for (int i = Size - 1; i >= 0; i--) if (Data[i]->Index == idx) { Data[i] = Data[Size - 1]; Size--; return; } }
};
struct ImTriangulator
{
static int EstimateTriangleCount(int points_count) { return (points_count < 3) ? 0 : points_count - 2; }
static int EstimateScratchBufferSize(int points_count) { return sizeof(ImTriangulatorNode) * points_count + sizeof(ImTriangulatorNode*) * points_count * 2; }
void Init(const ImVec2* points, int points_count, void* scratch_buffer);
void GetNextTriangle(unsigned int out_triangle[3]); // Return relative indexes for next triangle
// Internal functions
void BuildNodes(const ImVec2* points, int points_count);
void BuildReflexes();
void BuildEars();
void FlipNodeList();
bool IsEar(int i0, int i1, int i2, const ImVec2& v0, const ImVec2& v1, const ImVec2& v2) const;
void ReclassifyNode(ImTriangulatorNode* node);
// Internal members
int _TrianglesLeft = 0;
ImTriangulatorNode* _Nodes = NULL;
ImTriangulatorNodeSpan _Ears;
ImTriangulatorNodeSpan _Reflexes;
};
// Distribute storage for nodes, ears and reflexes.
// FIXME-OPT: if everything is convex, we could report it to caller and let it switch to an convex renderer
// (this would require first building reflexes to bail to convex if empty, without even building nodes)
void ImTriangulator::Init(const ImVec2* points, int points_count, void* scratch_buffer)
{
IM_ASSERT(scratch_buffer != NULL && points_count >= 3);
_TrianglesLeft = EstimateTriangleCount(points_count);
_Nodes = (ImTriangulatorNode*)scratch_buffer; // points_count x Node
_Ears.Data = (ImTriangulatorNode**)(_Nodes + points_count); // points_count x Node*
_Reflexes.Data = (ImTriangulatorNode**)(_Nodes + points_count) + points_count; // points_count x Node*
BuildNodes(points, points_count);
BuildReflexes();
BuildEars();
}
void ImTriangulator::BuildNodes(const ImVec2* points, int points_count)
{
for (int i = 0; i < points_count; i++)
{
_Nodes[i].Type = ImTriangulatorNodeType_Convex;
_Nodes[i].Index = i;
_Nodes[i].Pos = points[i];
_Nodes[i].Next = _Nodes + i + 1;
_Nodes[i].Prev = _Nodes + i - 1;
}
_Nodes[0].Prev = _Nodes + points_count - 1;
_Nodes[points_count - 1].Next = _Nodes;
}
void ImTriangulator::BuildReflexes()
{
ImTriangulatorNode* n1 = _Nodes;
for (int i = _TrianglesLeft; i >= 0; i--, n1 = n1->Next)
{
if (ImTriangleIsClockwise(n1->Prev->Pos, n1->Pos, n1->Next->Pos))
continue;
n1->Type = ImTriangulatorNodeType_Reflex;
_Reflexes.push_back(n1);
}
}
void ImTriangulator::BuildEars()
{
ImTriangulatorNode* n1 = _Nodes;
for (int i = _TrianglesLeft; i >= 0; i--, n1 = n1->Next)
{
if (n1->Type != ImTriangulatorNodeType_Convex)
continue;
if (!IsEar(n1->Prev->Index, n1->Index, n1->Next->Index, n1->Prev->Pos, n1->Pos, n1->Next->Pos))
continue;
n1->Type = ImTriangulatorNodeType_Ear;
_Ears.push_back(n1);
}
}
void ImTriangulator::GetNextTriangle(unsigned int out_triangle[3])
{
if (_Ears.Size == 0)
{
FlipNodeList();
ImTriangulatorNode* node = _Nodes;
for (int i = _TrianglesLeft; i >= 0; i--, node = node->Next)
node->Type = ImTriangulatorNodeType_Convex;
_Reflexes.Size = 0;
BuildReflexes();
BuildEars();
// If we still don't have ears, it means geometry is degenerated.
if (_Ears.Size == 0)
{
// Return first triangle available, mimicking the behavior of convex fill.
IM_ASSERT(_TrianglesLeft > 0); // Geometry is degenerated
_Ears.Data[0] = _Nodes;
_Ears.Size = 1;
}
}
ImTriangulatorNode* ear = _Ears.Data[--_Ears.Size];
out_triangle[0] = ear->Prev->Index;
out_triangle[1] = ear->Index;
out_triangle[2] = ear->Next->Index;
ear->Unlink();
if (ear == _Nodes)
_Nodes = ear->Next;
ReclassifyNode(ear->Prev);
ReclassifyNode(ear->Next);
_TrianglesLeft--;
}
void ImTriangulator::FlipNodeList()
{
ImTriangulatorNode* prev = _Nodes;
ImTriangulatorNode* temp = _Nodes;
ImTriangulatorNode* current = _Nodes->Next;
prev->Next = prev;
prev->Prev = prev;
while (current != _Nodes)
{
temp = current->Next;
current->Next = prev;
prev->Prev = current;
_Nodes->Next = current;
current->Prev = _Nodes;
prev = current;
current = temp;
}
_Nodes = prev;
}
// A triangle is an ear is no other vertex is inside it. We can test reflexes vertices only (see reference algorithm)
bool ImTriangulator::IsEar(int i0, int i1, int i2, const ImVec2& v0, const ImVec2& v1, const ImVec2& v2) const
{
ImTriangulatorNode** p_end = _Reflexes.Data + _Reflexes.Size;
for (ImTriangulatorNode** p = _Reflexes.Data; p < p_end; p++)
{
ImTriangulatorNode* reflex = *p;
if (reflex->Index != i0 && reflex->Index != i1 && reflex->Index != i2)
if (ImTriangleContainsPoint(v0, v1, v2, reflex->Pos))
return false;
}
return true;
}
void ImTriangulator::ReclassifyNode(ImTriangulatorNode* n1)
{
// Classify node
ImTriangulatorNodeType type;
const ImTriangulatorNode* n0 = n1->Prev;
const ImTriangulatorNode* n2 = n1->Next;
if (!ImTriangleIsClockwise(n0->Pos, n1->Pos, n2->Pos))
type = ImTriangulatorNodeType_Reflex;
else if (IsEar(n0->Index, n1->Index, n2->Index, n0->Pos, n1->Pos, n2->Pos))
type = ImTriangulatorNodeType_Ear;
else
type = ImTriangulatorNodeType_Convex;
// Update lists when a type changes
if (type == n1->Type)
return;
if (n1->Type == ImTriangulatorNodeType_Reflex)
_Reflexes.find_erase_unsorted(n1->Index);
else if (n1->Type == ImTriangulatorNodeType_Ear)
_Ears.find_erase_unsorted(n1->Index);
if (type == ImTriangulatorNodeType_Reflex)
_Reflexes.push_back(n1);
else if (type == ImTriangulatorNodeType_Ear)
_Ears.push_back(n1);
n1->Type = type;
}
// Use ear-clipping algorithm to triangulate a simple polygon (no self-interaction, no holes).
// (Reminder: we don't perform any coarse clipping/culling in ImDrawList layer!
// It is up to caller to ensure not making costly calls that will be outside of visible area.
// As concave fill is noticeably more expensive than other primitives, be mindful of this...
// Caller can build AABB of points, and avoid filling if 'draw_list->_CmdHeader.ClipRect.Overlays(points_bb) == false')
void ImDrawList::AddConcavePolyFilled(const ImVec2* points, const int points_count, ImU32 col)
{
if (points_count < 3 || (col & IM_COL32_A_MASK) == 0)
return;
const ImVec2 uv = _Data->TexUvWhitePixel;
ImTriangulator triangulator;
unsigned int triangle[3];
if (Flags & ImDrawListFlags_AntiAliasedFill)
{
// Anti-aliased Fill
const float AA_SIZE = _FringeScale;
const ImU32 col_trans = col & ~IM_COL32_A_MASK;
const int idx_count = (points_count - 2) * 3 + points_count * 6;
const int vtx_count = (points_count * 2);
PrimReserve(idx_count, vtx_count);
// Add indexes for fill
unsigned int vtx_inner_idx = _VtxCurrentIdx;
unsigned int vtx_outer_idx = _VtxCurrentIdx + 1;
_Data->TempBuffer.reserve_discard((ImTriangulator::EstimateScratchBufferSize(points_count) + sizeof(ImVec2)) / sizeof(ImVec2));
triangulator.Init(points, points_count, _Data->TempBuffer.Data);
while (triangulator._TrianglesLeft > 0)
{
triangulator.GetNextTriangle(triangle);
_IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx + (triangle[0] << 1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + (triangle[1] << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_inner_idx + (triangle[2] << 1));
_IdxWritePtr += 3;
}
// Compute normals
_Data->TempBuffer.reserve_discard(points_count);
ImVec2* temp_normals = _Data->TempBuffer.Data;
for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++)
{
const ImVec2& p0 = points[i0];
const ImVec2& p1 = points[i1];
float dx = p1.x - p0.x;
float dy = p1.y - p0.y;
IM_NORMALIZE2F_OVER_ZERO(dx, dy);
temp_normals[i0].x = dy;
temp_normals[i0].y = -dx;
}
for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++)
{
// Average normals
const ImVec2& n0 = temp_normals[i0];
const ImVec2& n1 = temp_normals[i1];
float dm_x = (n0.x + n1.x) * 0.5f;
float dm_y = (n0.y + n1.y) * 0.5f;
IM_FIXNORMAL2F(dm_x, dm_y);
dm_x *= AA_SIZE * 0.5f;
dm_y *= AA_SIZE * 0.5f;
// Add vertices
_VtxWritePtr[0].pos.x = (points[i1].x - dm_x); _VtxWritePtr[0].pos.y = (points[i1].y - dm_y); _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; // Inner
_VtxWritePtr[1].pos.x = (points[i1].x + dm_x); _VtxWritePtr[1].pos.y = (points[i1].y + dm_y); _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col_trans; // Outer
_VtxWritePtr += 2;
// Add indexes for fringes
_IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + (i0 << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1));
_IdxWritePtr[3] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1)); _IdxWritePtr[4] = (ImDrawIdx)(vtx_outer_idx + (i1 << 1)); _IdxWritePtr[5] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1));
_IdxWritePtr += 6;
}
_VtxCurrentIdx += (ImDrawIdx)vtx_count;
}
else
{
// Non Anti-aliased Fill
const int idx_count = (points_count - 2) * 3;
const int vtx_count = points_count;
PrimReserve(idx_count, vtx_count);
for (int i = 0; i < vtx_count; i++)
{
_VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col;
_VtxWritePtr++;
}
_Data->TempBuffer.reserve_discard((ImTriangulator::EstimateScratchBufferSize(points_count) + sizeof(ImVec2)) / sizeof(ImVec2));
triangulator.Init(points, points_count, _Data->TempBuffer.Data);
while (triangulator._TrianglesLeft > 0)
{
triangulator.GetNextTriangle(triangle);
_IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx + triangle[0]); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + triangle[1]); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + triangle[2]);
_IdxWritePtr += 3;
}
_VtxCurrentIdx += (ImDrawIdx)vtx_count;
}
}
//-----------------------------------------------------------------------------
// [SECTION] ImDrawListSplitter
@@ -2678,8 +2991,8 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
int unscaled_ascent, unscaled_descent, unscaled_line_gap;
stbtt_GetFontVMetrics(&src_tmp.FontInfo, &unscaled_ascent, &unscaled_descent, &unscaled_line_gap);
const float ascent = ImTrunc(unscaled_ascent * font_scale + ((unscaled_ascent > 0.0f) ? +1 : -1));
const float descent = ImTrunc(unscaled_descent * font_scale + ((unscaled_descent > 0.0f) ? +1 : -1));
const float ascent = ImCeil(unscaled_ascent * font_scale);
const float descent = ImFloor(unscaled_descent * font_scale);
ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent);
const float font_off_x = cfg.GlyphOffset.x;
const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent);
@@ -3774,6 +4087,8 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im
{
x = start_x;
y += line_height;
if (y > clip_rect.w)
break; // break out of main loop
word_wrap_eol = NULL;
s = CalcWordWrapNextLineStartA(s, text_end); // Wrapping skips upcoming blanks
continue;
@@ -4012,8 +4327,8 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im
}
else
{
draw_list->PathArcTo(ImVec2(x0, p1.y - rounding), rounding, IM_PI - arc0_e, IM_PI - arc0_b, 3); // BL
draw_list->PathArcTo(ImVec2(x0, p0.y + rounding), rounding, IM_PI + arc0_b, IM_PI + arc0_e, 3); // TR
draw_list->PathArcTo(ImVec2(x0, p1.y - rounding), rounding, IM_PI - arc0_e, IM_PI - arc0_b); // BL
draw_list->PathArcTo(ImVec2(x0, p0.y + rounding), rounding, IM_PI + arc0_b, IM_PI + arc0_e); // TR
}
if (p1.x > rect.Min.x + rounding)
{
@@ -4032,8 +4347,8 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im
}
else
{
draw_list->PathArcTo(ImVec2(x1, p0.y + rounding), rounding, -arc1_e, -arc1_b, 3); // TR
draw_list->PathArcTo(ImVec2(x1, p1.y - rounding), rounding, +arc1_b, +arc1_e, 3); // BR
draw_list->PathArcTo(ImVec2(x1, p0.y + rounding), rounding, -arc1_e, -arc1_b); // TR
draw_list->PathArcTo(ImVec2(x1, p1.y - rounding), rounding, +arc1_b, +arc1_e); // BR
}
}
draw_list->PathFillConvex(col);
@@ -4231,8 +4546,8 @@ static unsigned int stb_decompress(unsigned char *output, const unsigned char *i
//-----------------------------------------------------------------------------
// ProggyClean.ttf
// Copyright (c) 2004, 2005 Tristan Grimmer
// MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip)
// Download and more information at http://upperbounds.net
// MIT license (see License.txt in http://www.proggyfonts.net/index.php?menu=download)
// Download and more information at http://www.proggyfonts.net or http://upperboundsinteractive.com/fonts.php
//-----------------------------------------------------------------------------
// File: 'ProggyClean.ttf' (41208 bytes)
// Exported using misc/fonts/binary_to_compressed_c.cpp (with compression + base85 string encoding).

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.90.0
// dear imgui, v1.90.8
// (tables and columns code)
/*
@@ -24,8 +24,9 @@ Index of this file:
*/
// Navigating this file:
// - In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in 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
@@ -227,6 +228,7 @@ Index of this file:
#pragma clang diagnostic ignored "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_')
#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access
#elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
@@ -318,6 +320,12 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
IM_ASSERT(inner_width >= 0.0f);
// If an outer size is specified ahead we will be able to early out when not visible. Exact clipping criteria may evolve.
// FIXME: coarse clipping because access to table data causes two issues:
// - instance numbers varying/unstable. may not be a direct problem for users, but could make outside access broken or confusing, e.g. TestEngine.
// - can't implement support for ImGuiChildFlags_ResizeY as we need to somehow pull the height data from somewhere. this also needs stable instance numbers.
// The side-effects of accessing table data on coarse clip would be:
// - always reserving the pooled ImGuiTable data ahead for a fully clipped table (minor IMHO). Also the 'outer_window_is_measuring_size' criteria may already be defeating this in some situations.
// - always performing the GetOrAddByKey() O(log N) query in g.Tables.Map[].
const bool use_child_window = (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0;
const ImVec2 avail_size = GetContentRegionAvail();
const ImVec2 actual_outer_size = CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f);
@@ -326,12 +334,16 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
if (use_child_window && IsClippedEx(outer_rect, 0) && !outer_window_is_measuring_size)
{
ItemSize(outer_rect);
ItemAdd(outer_rect, id);
return false;
}
// [DEBUG] Debug break requested by user
if (g.DebugBreakInTable == id)
IM_DEBUG_BREAK();
// Acquire storage for the table
ImGuiTable* table = g.Tables.GetOrAddByKey(id);
const ImGuiTableFlags table_last_flags = table->Flags;
// Acquire temporary buffers
const int table_idx = g.Tables.GetIndex(table);
@@ -349,6 +361,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
// Initialize
const int previous_frame_active = table->LastFrameActive;
const int instance_no = (previous_frame_active != g.FrameCount) ? 0 : table->InstanceCurrent + 1;
const ImGuiTableFlags previous_flags = table->Flags;
table->ID = id;
table->Flags = flags;
table->LastFrameActive = g.FrameCount;
@@ -395,7 +408,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
SetNextWindowContentSize(ImVec2(override_content_size.x != FLT_MAX ? override_content_size.x : 0.0f, override_content_size.y != FLT_MAX ? override_content_size.y : 0.0f));
// Reset scroll if we are reactivating it
if ((table_last_flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) == 0)
if ((previous_flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) == 0)
SetNextWindowScroll(ImVec2(0.0f, 0.0f));
// Create scrolling region (without border and zero window padding)
@@ -424,6 +437,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
// For non-scrolling tables, WorkRect == OuterRect == InnerRect.
// 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;
}
// Push a standardized ID for both child-using and not-child-using tables
@@ -494,7 +508,8 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->DeclColumnsCount = table->AngledHeadersCount = 0;
if (previous_frame_active + 1 < g.FrameCount)
table->IsActiveIdInTable = false;
temp_data->AngledheadersExtraWidth = 0.0f;
table->AngledHeadersHeight = 0.0f;
temp_data->AngledHeadersExtraWidth = 0.0f;
// Using opaque colors facilitate overlapping lines of the grid, otherwise we'd need to improve TableDrawBorders()
table->BorderColorStrong = GetColorU32(ImGuiCol_TableBorderStrong);
@@ -507,7 +522,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
if (inner_window != outer_window) // So EndChild() within the inner window can restore the table properly.
inner_window->DC.CurrentTableIdx = table_idx;
if ((table_last_flags & ImGuiTableFlags_Reorderable) && (flags & ImGuiTableFlags_Reorderable) == 0)
if ((previous_flags & ImGuiTableFlags_Reorderable) && (flags & ImGuiTableFlags_Reorderable) == 0)
table->IsResetDisplayOrderRequest = true;
// Mark as used to avoid GC
@@ -1062,6 +1077,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// - ClipRect.Max.x: using WorkMaxX instead of MaxX (aka including padding) makes things more consistent when resizing down, tho slightly detrimental to visibility in very-small column.
// - ClipRect.Max.x: using MaxX makes it easier for header to receive hover highlight with no discontinuity and display sorting arrow.
// - FIXME-TABLE: We want equal width columns to have equal (ClipRect.Max.x - WorkMinX) width, which means ClipRect.max.x cannot stray off host_clip_rect.Max.x else right-most column may appear shorter.
const float previous_instance_work_min_x = column->WorkMinX;
column->WorkMinX = column->MinX + table->CellPaddingX + table->CellSpacingX1;
column->WorkMaxX = column->MaxX - table->CellPaddingX - table->CellSpacingX2; // Expected max
column->ItemWidth = ImTrunc(column->WidthGiven * 0.65f);
@@ -1114,8 +1130,22 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// column->WorkMinX = ImLerp(column->WorkMinX, ImMax(column->StartX, column->MaxX - column->ContentWidthRowsUnfrozen), 0.5f);
// Reset content width variables
column->ContentMaxXFrozen = column->ContentMaxXUnfrozen = column->WorkMinX;
column->ContentMaxXHeadersUsed = column->ContentMaxXHeadersIdeal = column->WorkMinX;
if (table->InstanceCurrent == 0)
{
column->ContentMaxXFrozen = column->WorkMinX;
column->ContentMaxXUnfrozen = column->WorkMinX;
column->ContentMaxXHeadersUsed = column->WorkMinX;
column->ContentMaxXHeadersIdeal = column->WorkMinX;
}
else
{
// As we store an absolute value to make per-cell updates faster, we need to offset values used for width computation.
const float offset_from_previous_instance = column->WorkMinX - previous_instance_work_min_x;
column->ContentMaxXFrozen += offset_from_previous_instance;
column->ContentMaxXUnfrozen += offset_from_previous_instance;
column->ContentMaxXHeadersUsed += offset_from_previous_instance;
column->ContentMaxXHeadersIdeal += offset_from_previous_instance;
}
// Don't decrement auto-fit counters until container window got a chance to submit its items
if (table->HostSkipItems == false)
@@ -1234,9 +1264,9 @@ void ImGui::TableUpdateBorders(ImGuiTable* table)
// really problematic (whereas the actual visual will be displayed in EndTable() and using the current frame height).
// Actual columns highlight/render will be performed in EndTable() and not be affected.
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
const float hit_half_width = TABLE_RESIZE_SEPARATOR_HALF_THICKNESS;
const float hit_half_width = ImTrunc(TABLE_RESIZE_SEPARATOR_HALF_THICKNESS * g.CurrentDpiScale);
const float hit_y1 = (table->FreezeRowsCount >= 1 ? table->OuterRect.Min.y : table->WorkRect.Min.y) + table->AngledHeadersHeight;
const float hit_y2_body = ImMax(table->OuterRect.Max.y, hit_y1 + table_instance->LastOuterHeight);
const float hit_y2_body = ImMax(table->OuterRect.Max.y, hit_y1 + table_instance->LastOuterHeight - table->AngledHeadersHeight);
const float hit_y2_head = hit_y1 + table_instance->LastTopHeadersRowHeight;
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
@@ -1340,7 +1370,7 @@ void ImGui::EndTable()
max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].WorkMaxX + table->CellPaddingX + table->OuterPaddingX - outer_padding_for_border);
if (table->ResizedColumn != -1)
max_pos_x = ImMax(max_pos_x, table->ResizeLockMinContentsX2);
table->InnerWindow->DC.CursorMaxPos.x = max_pos_x + table->TempData->AngledheadersExtraWidth;
table->InnerWindow->DC.CursorMaxPos.x = max_pos_x + table->TempData->AngledHeadersExtraWidth;
}
// Pop clipping rect
@@ -1411,7 +1441,7 @@ void ImGui::EndTable()
if (table->ResizedColumn != -1 && table->InstanceCurrent == table->InstanceInteracted)
{
ImGuiTableColumn* column = &table->Columns[table->ResizedColumn];
const float new_x2 = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + TABLE_RESIZE_SEPARATOR_HALF_THICKNESS);
const float new_x2 = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + ImTrunc(TABLE_RESIZE_SEPARATOR_HALF_THICKNESS * g.CurrentDpiScale));
const float new_width = ImTrunc(new_x2 - column->MinX - table->CellSpacingX1 - table->CellPaddingX * 2.0f);
table->ResizedColumnNextWidth = new_width;
}
@@ -1440,7 +1470,10 @@ void ImGui::EndTable()
// CursorPosPrevLine and CursorMaxPos manually. That should be a more general layout feature, see same problem e.g. #3414)
if (inner_window != outer_window)
{
short backup_nav_layers_active_mask = inner_window->DC.NavLayersActiveMask;
inner_window->DC.NavLayersActiveMask |= 1 << ImGuiNavLayer_Main; // So empty table don't appear to navigate differently.
EndChild();
inner_window->DC.NavLayersActiveMask = backup_nav_layers_active_mask;
}
else
{
@@ -1458,9 +1491,13 @@ void ImGui::EndTable()
}
else if (temp_data->UserOuterSize.x <= 0.0f)
{
const float decoration_size = table->TempData->AngledheadersExtraWidth + ((table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.x : 0.0f);
outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth + decoration_size - temp_data->UserOuterSize.x);
outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth));
// Some references for this: #7651 + tests "table_reported_size", "table_reported_size_outer" equivalent Y block
// - Checking for ImGuiTableFlags_ScrollX/ScrollY flag makes us a frame ahead when disabling those flags.
// - FIXME-TABLE: Would make sense to pre-compute expected scrollbar visibility/sizes to generally save a frame of feedback.
const float inner_content_max_x = table->OuterRect.Min.x + table->ColumnsAutoFitWidth; // Slightly misleading name but used for code symmetry with inner_content_max_y
const float decoration_size = table->TempData->AngledHeadersExtraWidth + ((table->Flags & ImGuiTableFlags_ScrollY) ? inner_window->ScrollbarSizes.x : 0.0f);
outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, inner_content_max_x + decoration_size - temp_data->UserOuterSize.x);
outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, inner_content_max_x + decoration_size));
}
else
{
@@ -1468,9 +1505,9 @@ void ImGui::EndTable()
}
if (temp_data->UserOuterSize.y <= 0.0f)
{
const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollY) ? inner_window->ScrollbarSizes.y : 0.0f;
const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.y : 0.0f;
outer_window->DC.IdealMaxPos.y = ImMax(outer_window->DC.IdealMaxPos.y, inner_content_max_y + decoration_size - temp_data->UserOuterSize.y);
outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, inner_content_max_y));
outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, inner_content_max_y + decoration_size));
}
else
{
@@ -1563,6 +1600,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo
}
// Store name (append with zero-terminator in contiguous buffer)
// FIXME: If we recorded the number of \n in names we could compute header row height
column->NameOffset = -1;
if (label != NULL && label[0] != 0)
{
@@ -1885,7 +1923,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
if (is_visible)
{
// Update data for TableGetHoveredRow()
if (table->HoveredColumnBody != -1 && g.IO.MousePos.y >= bg_y1 && g.IO.MousePos.y < bg_y2)
if (table->HoveredColumnBody != -1 && g.IO.MousePos.y >= bg_y1 && g.IO.MousePos.y < bg_y2 && table_instance->HoveredRowNext < 0)
table_instance->HoveredRowNext = table->CurrentRow;
// Decide of background color for the row
@@ -1940,7 +1978,8 @@ void ImGui::TableEndRow(ImGuiTable* table)
cell_bg_rect.ClipWith(table->BgClipRect);
cell_bg_rect.Min.x = ImMax(cell_bg_rect.Min.x, column->ClipRect.Min.x); // So that first column after frozen one gets clipped when scrolling
cell_bg_rect.Max.x = ImMin(cell_bg_rect.Max.x, column->MaxX);
window->DrawList->AddRectFilled(cell_bg_rect.Min, cell_bg_rect.Max, cell_data->BgColor);
if (cell_bg_rect.Min.y < cell_bg_rect.Max.y)
window->DrawList->AddRectFilled(cell_bg_rect.Min, cell_bg_rect.Max, cell_data->BgColor);
}
}
@@ -2150,6 +2189,8 @@ void ImGui::TableEndCell(ImGuiTable* table)
// - TableSetColumnWidthAutoAll() [Internal]
// - TableUpdateColumnsWeightFromWidth() [Internal]
//-------------------------------------------------------------------------
// Note that actual columns widths are computed in TableUpdateLayout().
//-------------------------------------------------------------------------
// Maximum column content width given current layout. Use column->MinX so this value on a per-column basis.
float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n)
@@ -2759,7 +2800,7 @@ ImGuiTableSortSpecs* ImGui::TableGetSortSpecs()
static inline ImGuiSortDirection TableGetColumnAvailSortDirection(ImGuiTableColumn* column, int n)
{
IM_ASSERT(n < column->SortDirectionsAvailCount);
return (column->SortDirectionsAvailList >> (n << 1)) & 0x03;
return (ImGuiSortDirection)((column->SortDirectionsAvailList >> (n << 1)) & 0x03);
}
// Fix sort direction if currently set on a value which is unavailable (e.g. activating NoSortAscending/NoSortDescending)
@@ -2900,6 +2941,7 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table)
}
// Write output
// May be able to move all SortSpecs data from table (48 bytes) to ImGuiTableTempData if we decide to write it back on every BeginTable()
ImGuiTableColumnSortSpecs* sort_specs = (table->SortSpecsCount == 0) ? NULL : (table->SortSpecsCount == 1) ? &table->SortSpecsSingle : table->SortSpecsMulti.Data;
if (dirty && sort_specs != NULL)
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
@@ -2912,7 +2954,7 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table)
sort_spec->ColumnUserID = column->UserID;
sort_spec->ColumnIndex = (ImGuiTableColumnIdx)column_n;
sort_spec->SortOrder = (ImGuiTableColumnIdx)column->SortOrder;
sort_spec->SortDirection = column->SortDirection;
sort_spec->SortDirection = (ImGuiSortDirection)column->SortDirection;
}
table->SortSpecs.Specs = sort_specs;
@@ -2923,6 +2965,7 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table)
// [SECTION] Tables: Headers
//-------------------------------------------------------------------------
// - TableGetHeaderRowHeight() [Internal]
// - TableGetHeaderAngledMaxLabelWidth() [Internal]
// - TableHeadersRow()
// - TableHeader()
// - TableAngledHeadersRow()
@@ -2954,12 +2997,12 @@ float ImGui::TableGetHeaderAngledMaxLabelWidth()
if (IM_BITARRAY_TESTBIT(table->EnabledMaskByIndex, column_n))
if (table->Columns[column_n].Flags & ImGuiTableColumnFlags_AngledHeader)
width = ImMax(width, CalcTextSize(TableGetColumnName(table, column_n), NULL, true).x);
return width + g.Style.CellPadding.x * 2.0f;
return width + g.Style.CellPadding.y * 2.0f; // Swap padding
}
// [Public] This is a helper to output TableHeader() calls based on the column names declared in TableSetupColumn().
// The intent is that advanced users willing to create customized headers would not need to use this helper
// and can create their own! For example: TableHeader() may be preceeded by Checkbox() or other custom widgets.
// and can create their own! For example: TableHeader() may be preceded by Checkbox() or other custom widgets.
// See 'Demo->Tables->Custom headers' for a demonstration of implementing a custom version of this.
// This code is constructed to not make much use of internal functions, as it is intended to be a template to copy.
// FIXME-TABLE: TableOpenContextMenu() and TableGetHeaderRowHeight() are not public.
@@ -3078,7 +3121,7 @@ void ImGui::TableHeader(const char* label)
if ((table->RowFlags & ImGuiTableRowFlags_Headers) == 0)
TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_TableHeaderBg), table->CurrentColumn);
}
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding);
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_Compact | ImGuiNavHighlightFlags_NoRounding);
if (held)
table->HeldHeaderColumn = (ImGuiTableColumnIdx)column_n;
window->DC.CursorPos.y -= g.Style.ItemSpacing.y * 0.5f;
@@ -3145,15 +3188,43 @@ void ImGui::TableHeader(const char* label)
}
// Unlike TableHeadersRow() it is not expected that you can reimplement or customize this with custom widgets.
// FIXME: highlight without ImGuiTableFlags_HighlightHoveredColumn
// FIXME: No hit-testing/button on the angled header.
void ImGui::TableAngledHeadersRow()
{
ImGuiContext& g = *GImGui;
TableAngledHeadersRowEx(g.Style.TableAngledHeadersAngle, 0.0f);
ImGuiTable* table = g.CurrentTable;
ImGuiTableTempData* temp_data = table->TempData;
temp_data->AngledHeadersRequests.resize(0);
temp_data->AngledHeadersRequests.reserve(table->ColumnsEnabledCount);
// Which column needs highlight?
const ImGuiID row_id = GetID("##AngledHeaders");
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
int highlight_column_n = table->HighlightColumnHeader;
if (highlight_column_n == -1 && table->HoveredColumnBody != -1)
if (table_instance->HoveredRowLast == 0 && table->HoveredColumnBorder == -1 && (g.ActiveId == 0 || g.ActiveId == row_id || (table->IsActiveIdInTable || g.DragDropActive)))
highlight_column_n = table->HoveredColumnBody;
// Build up request
ImU32 col_header_bg = GetColorU32(ImGuiCol_TableHeaderBg);
ImU32 col_text = GetColorU32(ImGuiCol_Text);
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
if (IM_BITARRAY_TESTBIT(table->EnabledMaskByDisplayOrder, order_n))
{
const int column_n = table->DisplayOrderToIndex[order_n];
ImGuiTableColumn* column = &table->Columns[column_n];
if ((column->Flags & ImGuiTableColumnFlags_AngledHeader) == 0) // Note: can't rely on ImGuiTableColumnFlags_IsVisible test here.
continue;
ImGuiTableHeaderData request = { (ImGuiTableColumnIdx)column_n, col_text, col_header_bg, (column_n == highlight_column_n) ? GetColorU32(ImGuiCol_Header) : 0 };
temp_data->AngledHeadersRequests.push_back(request);
}
// Render row
TableAngledHeadersRowEx(row_id, g.Style.TableAngledHeadersAngle, 0.0f, temp_data->AngledHeadersRequests.Data, temp_data->AngledHeadersRequests.Size);
}
void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width)
// Important: data must be fed left to right
void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label_width, const ImGuiTableHeaderData* data, int data_count)
{
ImGuiContext& g = *GImGui;
ImGuiTable* table = g.CurrentTable;
@@ -3176,45 +3247,41 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width)
// Calculate our base metrics and set angled headers data _before_ the first call to TableNextRow()
// FIXME-STYLE: Would it be better for user to submit 'max_label_width' or 'row_height' ? One can be derived from the other.
const float header_height = table->RowCellPaddingY * 2.0f + g.FontSize;
const float row_height = ImFabs(ImRotate(ImVec2(max_label_width, flip_label ? +header_height : -header_height), cos_a, sin_a).y);
const ImVec2 header_angled_vector = unit_right * (row_height / -sin_a);
const float header_height = g.FontSize + g.Style.CellPadding.x * 2.0f;
const float row_height = ImTrunc(ImFabs(ImRotate(ImVec2(max_label_width, flip_label ? +header_height : -header_height), cos_a, sin_a).y));
table->AngledHeadersHeight = row_height;
table->AngledHeadersSlope = (sin_a != 0.0f) ? (cos_a / sin_a) : 0.0f;
const ImVec2 header_angled_vector = unit_right * (row_height / -sin_a); // vector from bottom-left to top-left, and from bottom-right to top-right
// Declare row, override and draw our own background
TableNextRow(ImGuiTableRowFlags_Headers, row_height);
TableNextColumn();
const ImRect row_r(table->WorkRect.Min.x, table->BgClipRect.Min.y, table->WorkRect.Max.x, table->RowPosY2);
table->DrawSplitter->SetCurrentChannel(draw_list, TABLE_DRAW_CHANNEL_BG0);
float clip_rect_min_x = table->BgClipRect.Min.x;
if (table->FreezeColumnsCount > 0)
clip_rect_min_x = ImMax(clip_rect_min_x, table->Columns[table->FreezeColumnsCount - 1].MaxX);
TableSetBgColor(ImGuiTableBgTarget_RowBg0, 0); // Cancel
PushClipRect(table->BgClipRect.Min, table->BgClipRect.Max, false); // Span all columns
draw_list->AddRectFilled(table->BgClipRect.Min, table->BgClipRect.Max, GetColorU32(ImGuiCol_TableHeaderBg, 0.25f)); // FIXME-STYLE: Change row background with an arbitrary color.
draw_list->AddRectFilled(ImVec2(table->BgClipRect.Min.x, row_r.Min.y), ImVec2(table->BgClipRect.Max.x, row_r.Max.y), GetColorU32(ImGuiCol_TableHeaderBg, 0.25f)); // FIXME-STYLE: Change row background with an arbitrary color.
PushClipRect(ImVec2(clip_rect_min_x, table->BgClipRect.Min.y), table->BgClipRect.Max, true); // Span all columns
const ImRect row_r(table->WorkRect.Min.x, table->BgClipRect.Min.y, table->WorkRect.Max.x, window->DC.CursorPos.y + row_height);
const ImGuiID row_id = GetID("##AngledHeaders");
ButtonBehavior(row_r, row_id, NULL, NULL);
KeepAliveID(row_id);
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
int highlight_column_n = table->HighlightColumnHeader;
if (highlight_column_n == -1 && table->HoveredColumnBody != -1)
if (table_instance->HoveredRowLast == 0 && table->HoveredColumnBorder == -1 && (g.ActiveId == 0 || g.ActiveId == row_id || (table->IsActiveIdInTable || g.DragDropActive)))
highlight_column_n = table->HoveredColumnBody;
const float ascent_scaled = g.Font->Ascent * (g.FontSize / g.Font->FontSize); // FIXME: Standardize those scaling factors better
const float line_off_for_ascent_x = (ImMax((g.FontSize - ascent_scaled) * 0.5f, 0.0f) / -sin_a) * (flip_label ? -1.0f : 1.0f);
const ImVec2 padding = g.Style.CellPadding; // We will always use swapped component
const ImVec2 align = g.Style.TableAngledHeadersTextAlign;
// Draw background and labels in first pass, then all borders.
float max_x = 0.0f;
for (int pass = 0; pass < 2; pass++)
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
for (int order_n = 0; order_n < data_count; order_n++)
{
if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByDisplayOrder, order_n))
continue;
const int column_n = table->DisplayOrderToIndex[order_n];
const ImGuiTableHeaderData* request = &data[order_n];
const int column_n = request->Index;
ImGuiTableColumn* column = &table->Columns[column_n];
if ((column->Flags & ImGuiTableColumnFlags_AngledHeader) == 0) // Note: can't rely on ImGuiTableColumnFlags_IsVisible test here.
continue;
ImVec2 bg_shape[4];
bg_shape[0] = ImVec2(column->MaxX, row_r.Max.y);
@@ -3224,28 +3291,60 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width)
if (pass == 0)
{
// Draw shape
draw_list->AddQuadFilled(bg_shape[0], bg_shape[1], bg_shape[2], bg_shape[3], GetColorU32(ImGuiCol_TableHeaderBg));
if (column_n == highlight_column_n)
draw_list->AddQuadFilled(bg_shape[0], bg_shape[1], bg_shape[2], bg_shape[3], GetColorU32(ImGuiCol_Header)); // Highlight on hover
//draw_list->AddQuad(bg_shape[0], bg_shape[1], bg_shape[2], bg_shape[3], GetColorU32(ImGuiCol_TableBorderLight), 1.0f);
draw_list->AddQuadFilled(bg_shape[0], bg_shape[1], bg_shape[2], bg_shape[3], request->BgColor0);
draw_list->AddQuadFilled(bg_shape[0], bg_shape[1], bg_shape[2], bg_shape[3], request->BgColor1); // Optional highlight
max_x = ImMax(max_x, bg_shape[3].x);
// Draw label (first draw at an offset where RenderTextXXX() function won't meddle with applying current ClipRect, then transform to final offset)
// FIXME: May be worth tidying up all those operations to make them easier to understand.
// Draw label
// - First draw at an offset where RenderTextXXX() function won't meddle with applying current ClipRect, then transform to final offset.
// - Handle multiple lines manually, as we want each lines to follow on the horizontal border, rather than see a whole block rotated.
const char* label_name = TableGetColumnName(table, column_n);
const float clip_width = max_label_width - (sin_a * table->RowCellPaddingY);
ImRect label_r(window->ClipRect.Min, window->ClipRect.Min + ImVec2(clip_width + (flip_label ? 0.0f : table->CellPaddingX), header_height + table->RowCellPaddingY));
ImVec2 label_size = CalcTextSize(label_name, NULL, true);
ImVec2 label_off = ImVec2(flip_label ? ImMax(0.0f, max_label_width - label_size.x - table->CellPaddingX) : table->CellPaddingX, table->RowCellPaddingY);
int vtx_idx_begin = draw_list->_VtxCurrentIdx;
RenderTextEllipsis(draw_list, label_r.Min + label_off, label_r.Max, label_r.Max.x, label_r.Max.x, label_name, NULL, &label_size);
//if (g.IO.KeyShift) { draw_list->AddRect(label_r.Min, label_r.Max, IM_COL32(0, 255, 0, 255), 0.0f, 0, 2.0f); }
int vtx_idx_end = draw_list->_VtxCurrentIdx;
const char* label_name_end = FindRenderedTextEnd(label_name);
const float line_off_step_x = (g.FontSize / -sin_a);
const int label_lines = ImTextCountLines(label_name, label_name_end);
// Rotate and offset label
ImVec2 pivot_in = label_r.GetBL();
ImVec2 pivot_out = ImVec2(column->WorkMinX, row_r.Max.y) + (flip_label ? (unit_right * clip_width) : ImVec2(header_height, 0.0f));
ShadeVertsTransformPos(draw_list, vtx_idx_begin, vtx_idx_end, pivot_in, label_cos_a, label_sin_a, pivot_out); // Rotate and offset
// 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;
line_off_curr_x += line_off_for_align_x - line_off_for_ascent_x;
// Register header width
column->ContentMaxXHeadersUsed = column->ContentMaxXHeadersIdeal = column->WorkMinX + ImCeil(label_lines * line_off_step_x - line_off_for_align_x);
while (label_name < label_name_end)
{
const char* label_name_eol = strchr(label_name, '\n');
if (label_name_eol == NULL)
label_name_eol = label_name_end;
// FIXME: Individual line clipping for right-most column is broken for negative angles.
ImVec2 label_size = CalcTextSize(label_name, label_name_eol);
float clip_width = max_label_width - padding.y; // Using padding.y*2.0f would be symmetrical but hide more text.
float clip_height = ImMin(label_size.y, column->ClipRect.Max.x - column->WorkMinX - line_off_curr_x);
ImRect clip_r(window->ClipRect.Min, window->ClipRect.Min + ImVec2(clip_width, clip_height));
int vtx_idx_begin = draw_list->_VtxCurrentIdx;
PushStyleColor(ImGuiCol_Text, request->TextColor);
RenderTextEllipsis(draw_list, clip_r.Min, clip_r.Max, clip_r.Max.x, clip_r.Max.x, label_name, label_name_eol, &label_size);
PopStyleColor();
int vtx_idx_end = draw_list->_VtxCurrentIdx;
// Up<>Down alignment
const float available_space = ImMax(clip_width - label_size.x + ImAbs(padding.x * cos_a) * 2.0f - ImAbs(padding.y * sin_a) * 2.0f, 0.0f);
const float vertical_offset = available_space * align.y * (flip_label ? -1.0f : 1.0f);
// Rotate and offset label
ImVec2 pivot_in = ImVec2(window->ClipRect.Min.x - vertical_offset, window->ClipRect.Min.y + label_size.y);
ImVec2 pivot_out = ImVec2(column->WorkMinX, row_r.Max.y);
line_off_curr_x += flip_label ? -line_off_step_x : line_off_step_x;
pivot_out += unit_right * padding.y;
if (flip_label)
pivot_out += unit_right * (clip_width - ImMax(0.0f, clip_width - label_size.x));
pivot_out.x += flip_label ? line_off_curr_x + line_off_step_x : line_off_curr_x;
ShadeVertsTransformPos(draw_list, vtx_idx_begin, vtx_idx_end, pivot_in, label_cos_a, label_sin_a, pivot_out); // Rotate and offset
//if (g.IO.KeyShift) { ImDrawList* fg_dl = GetForegroundDrawList(); vtx_idx_begin = fg_dl->_VtxCurrentIdx; fg_dl->AddRect(clip_r.Min, clip_r.Max, IM_COL32(0, 255, 0, 255), 0.0f, 0, 1.0f); ShadeVertsTransformPos(fg_dl, vtx_idx_begin, fg_dl->_VtxCurrentIdx, pivot_in, label_cos_a, label_sin_a, pivot_out); }
label_name = label_name_eol + 1;
}
}
if (pass == 1)
{
@@ -3255,7 +3354,7 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width)
}
PopClipRect();
PopClipRect();
table->TempData->AngledheadersExtraWidth = ImMax(0.0f, max_x - table->Columns[table->RightMostEnabledColumn].MaxX);
table->TempData->AngledHeadersExtraWidth = ImMax(0.0f, max_x - table->Columns[table->RightMostEnabledColumn].MaxX);
}
//-------------------------------------------------------------------------
@@ -3802,7 +3901,8 @@ static const char* DebugNodeTableGetSizingPolicyDesc(ImGuiTableFlags sizing_poli
void ImGui::DebugNodeTable(ImGuiTable* table)
{
const bool is_active = (table->LastFrameActive >= GetFrameCount() - 2); // Note that fully clipped early out scrolling tables will appear as inactive here.
ImGuiContext& g = *GImGui;
const bool is_active = (table->LastFrameActive >= g.FrameCount - 2); // Note that fully clipped early out scrolling tables will appear as inactive here.
if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
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(); }
@@ -3814,6 +3914,13 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
return;
if (table->InstanceCurrent > 0)
Text("** %d instances of same table! Some data below will refer to last instance.", table->InstanceCurrent + 1);
if (g.IO.ConfigDebugIsDebuggerPresent)
{
if (DebugBreakButton("**DebugBreak**", "in BeginTable()"))
g.DebugBreakInTable = table->ID;
SameLine();
}
bool clear_settings = SmallButton("Clear settings");
BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f) Sizing: '%s'", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight(), DebugNodeTableGetSizingPolicyDesc(table->Flags));
BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : "");
@@ -3950,7 +4057,7 @@ float ImGui::GetColumnNormFromOffset(const ImGuiOldColumns* columns, float offse
return offset / (columns->OffMaxX - columns->OffMinX);
}
static const float COLUMNS_HIT_RECT_HALF_WIDTH = 4.0f;
static const float COLUMNS_HIT_RECT_HALF_THICKNESS = 4.0f;
static float GetDraggedColumnOffset(ImGuiOldColumns* columns, int column_index)
{
@@ -3961,7 +4068,7 @@ static float GetDraggedColumnOffset(ImGuiOldColumns* columns, int column_index)
IM_ASSERT(column_index > 0); // We are not supposed to drag column 0.
IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index));
float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + COLUMNS_HIT_RECT_HALF_WIDTH - window->Pos.x;
float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + ImTrunc(COLUMNS_HIT_RECT_HALF_THICKNESS * g.CurrentDpiScale) - window->Pos.x;
x = ImMax(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing);
if ((columns->Flags & ImGuiOldColumnFlags_NoPreserveWidths))
x = ImMin(x, ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing);
@@ -4276,7 +4383,7 @@ void ImGui::EndColumns()
ImGuiOldColumnData* column = &columns->Columns[n];
float x = window->Pos.x + GetColumnOffset(n);
const ImGuiID column_id = columns->ID + ImGuiID(n);
const float column_hit_hw = COLUMNS_HIT_RECT_HALF_WIDTH;
const float column_hit_hw = ImTrunc(COLUMNS_HIT_RECT_HALF_THICKNESS * g.CurrentDpiScale);
const ImRect column_hit_rect(ImVec2(x - column_hit_hw, y1), ImVec2(x + column_hit_hw, y2));
if (!ItemAdd(column_hit_rect, column_id, NULL, ImGuiItemFlags_NoNav))
continue;

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,7 @@
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783)
// Grep for [DEAR IMGUI] to find the 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
// Development of this library was sponsored by RAD Game Tools
@@ -30,7 +31,7 @@
// DEPENDENCIES
//
// Uses the C runtime function 'memmove', which you can override
// by defining STB_TEXTEDIT_memmove before the implementation.
// by defining IMSTB_TEXTEDIT_memmove before the implementation.
// Uses no other functions. Performs no runtime allocations.
//
//
@@ -40,7 +41,7 @@
// 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
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual
// 1.10 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
// 1.9 (2016-08-27) customizable move-by-word
// 1.8 (2016-04-02) better keyboard handling when mouse button is down
// 1.7 (2015-09-13) change y range handling in case baseline is non-0
@@ -274,8 +275,8 @@
////
////
#ifndef INCLUDE_STB_TEXTEDIT_H
#define INCLUDE_STB_TEXTEDIT_H
#ifndef INCLUDE_IMSTB_TEXTEDIT_H
#define INCLUDE_IMSTB_TEXTEDIT_H
////////////////////////////////////////////////////////////////////////
//
@@ -286,33 +287,33 @@
// and undo state.
//
#ifndef STB_TEXTEDIT_UNDOSTATECOUNT
#define STB_TEXTEDIT_UNDOSTATECOUNT 99
#ifndef IMSTB_TEXTEDIT_UNDOSTATECOUNT
#define IMSTB_TEXTEDIT_UNDOSTATECOUNT 99
#endif
#ifndef STB_TEXTEDIT_UNDOCHARCOUNT
#define STB_TEXTEDIT_UNDOCHARCOUNT 999
#ifndef IMSTB_TEXTEDIT_UNDOCHARCOUNT
#define IMSTB_TEXTEDIT_UNDOCHARCOUNT 999
#endif
#ifndef STB_TEXTEDIT_CHARTYPE
#define STB_TEXTEDIT_CHARTYPE int
#ifndef IMSTB_TEXTEDIT_CHARTYPE
#define IMSTB_TEXTEDIT_CHARTYPE int
#endif
#ifndef STB_TEXTEDIT_POSITIONTYPE
#define STB_TEXTEDIT_POSITIONTYPE int
#ifndef IMSTB_TEXTEDIT_POSITIONTYPE
#define IMSTB_TEXTEDIT_POSITIONTYPE int
#endif
typedef struct
{
// private data
STB_TEXTEDIT_POSITIONTYPE where;
STB_TEXTEDIT_POSITIONTYPE insert_length;
STB_TEXTEDIT_POSITIONTYPE delete_length;
IMSTB_TEXTEDIT_POSITIONTYPE where;
IMSTB_TEXTEDIT_POSITIONTYPE insert_length;
IMSTB_TEXTEDIT_POSITIONTYPE delete_length;
int char_storage;
} StbUndoRecord;
typedef struct
{
// private data
StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT];
STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT];
StbUndoRecord undo_rec [IMSTB_TEXTEDIT_UNDOSTATECOUNT];
IMSTB_TEXTEDIT_CHARTYPE undo_char[IMSTB_TEXTEDIT_UNDOCHARCOUNT];
short undo_point, redo_point;
int undo_char_point, redo_char_point;
} StbUndoState;
@@ -371,7 +372,7 @@ typedef struct
float ymin,ymax; // height of row above and below baseline
int num_chars;
} StbTexteditRow;
#endif //INCLUDE_STB_TEXTEDIT_H
#endif //INCLUDE_IMSTB_TEXTEDIT_H
////////////////////////////////////////////////////////////////////////////
@@ -384,11 +385,11 @@ typedef struct
// implementation isn't include-guarded, since it might have indirectly
// included just the "header" portion
#ifdef STB_TEXTEDIT_IMPLEMENTATION
#ifdef IMSTB_TEXTEDIT_IMPLEMENTATION
#ifndef STB_TEXTEDIT_memmove
#ifndef IMSTB_TEXTEDIT_memmove
#include <string.h>
#define STB_TEXTEDIT_memmove memmove
#define IMSTB_TEXTEDIT_memmove memmove
#endif
@@ -398,7 +399,7 @@ typedef struct
//
// traverse the layout to locate the nearest character to a display position
static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y)
{
StbTexteditRow r;
int n = STB_TEXTEDIT_STRINGLEN(str);
@@ -458,7 +459,7 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
}
// API click: on mouse down, move the cursor to the clicked location, and reset the selection
static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
static void stb_textedit_click(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
{
// In single-line mode, just always make y = 0. This lets the drag keep working if the mouse
// goes off the top or bottom of the text
@@ -476,7 +477,7 @@ static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *stat
}
// API drag: on mouse drag, move the cursor and selection endpoint to the clicked location
static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
static void stb_textedit_drag(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
{
int p = 0;
@@ -502,11 +503,11 @@ static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state
//
// forward declarations
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state);
static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state);
static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length);
static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
typedef struct
{
@@ -518,7 +519,7 @@ typedef struct
// find the x/y location of a character, and remember info about the previous row in
// case we get a move-up event (for page up, we'll have to rescan)
static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line)
static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING *str, int n, int single_line)
{
StbTexteditRow r;
int prev_start = 0;
@@ -569,7 +570,7 @@ static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *s
#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
// make the selection/cursor state valid if client altered the string
static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
static void stb_textedit_clamp(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
int n = STB_TEXTEDIT_STRINGLEN(str);
if (STB_TEXT_HAS_SELECTION(state)) {
@@ -583,7 +584,7 @@ static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *stat
}
// delete characters while updating undo
static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
static void stb_textedit_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
{
stb_text_makeundo_delete(str, state, where, len);
STB_TEXTEDIT_DELETECHARS(str, where, len);
@@ -591,7 +592,7 @@ static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *sta
}
// delete the section
static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
static void stb_textedit_delete_selection(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
stb_textedit_clamp(str, state);
if (STB_TEXT_HAS_SELECTION(state)) {
@@ -628,7 +629,7 @@ static void stb_textedit_move_to_first(STB_TexteditState *state)
}
// move cursor to last character of selection
static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
static void stb_textedit_move_to_last(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
if (STB_TEXT_HAS_SELECTION(state)) {
stb_textedit_sortselection(state);
@@ -640,13 +641,13 @@ static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditStat
}
#ifdef STB_TEXTEDIT_IS_SPACE
static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx )
static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx )
{
return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;
}
#ifndef STB_TEXTEDIT_MOVEWORDLEFT
static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )
static int stb_textedit_move_to_word_previous( IMSTB_TEXTEDIT_STRING *str, int c )
{
--c; // always move at least one character
while( c >= 0 && !is_word_boundary( str, c ) )
@@ -661,7 +662,7 @@ static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )
#endif
#ifndef STB_TEXTEDIT_MOVEWORDRIGHT
static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c )
static int stb_textedit_move_to_word_next( IMSTB_TEXTEDIT_STRING *str, int c )
{
const int len = STB_TEXTEDIT_STRINGLEN(str);
++c; // always move at least one character
@@ -688,7 +689,7 @@ static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state)
}
// API cut: delete selection
static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
static int stb_textedit_cut(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
if (STB_TEXT_HAS_SELECTION(state)) {
stb_textedit_delete_selection(str,state); // implicitly clamps
@@ -699,7 +700,7 @@ static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
}
// API paste: replace existing selection with passed-in text
static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE *text, int len)
{
// if there's a selection, the paste should delete it
stb_textedit_clamp(str, state);
@@ -720,14 +721,14 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta
#endif
// API key: process a keyboard input
static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
{
retry:
switch (key) {
default: {
int c = STB_TEXTEDIT_KEYTOTEXT(key);
if (c > 0) {
STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE) c;
IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE) c;
// can't add newline in single-line mode
if (c == '\n' && state->single_line)
@@ -892,8 +893,8 @@ retry:
x = row.x0;
for (i=0; i < row.num_chars; ++i) {
float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
break;
#endif
x += dx;
@@ -954,8 +955,8 @@ retry:
x = row.x0;
for (i=0; i < row.num_chars; ++i) {
float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
break;
#endif
x += dx;
@@ -1112,8 +1113,8 @@ retry:
static void stb_textedit_flush_redo(StbUndoState *state)
{
state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
state->redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT;
state->redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT;
}
// discard the oldest entry in the undo list
@@ -1125,13 +1126,13 @@ static void stb_textedit_discard_undo(StbUndoState *state)
int n = state->undo_rec[0].insert_length, i;
// delete n characters from all other records
state->undo_char_point -= n;
STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
IMSTB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(IMSTB_TEXTEDIT_CHARTYPE)));
for (i=0; i < state->undo_point; ++i)
if (state->undo_rec[i].char_storage >= 0)
state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it
}
--state->undo_point;
STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
IMSTB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
}
}
@@ -1141,7 +1142,7 @@ static void stb_textedit_discard_undo(StbUndoState *state)
// fill up even though the undo buffer didn't
static void stb_textedit_discard_redo(StbUndoState *state)
{
int k = STB_TEXTEDIT_UNDOSTATECOUNT-1;
int k = IMSTB_TEXTEDIT_UNDOSTATECOUNT-1;
if (state->redo_point <= k) {
// if the k'th undo state has characters, clean those up
@@ -1149,7 +1150,7 @@ static void stb_textedit_discard_redo(StbUndoState *state)
int n = state->undo_rec[k].insert_length, i;
// move the remaining redo character data to the end of the buffer
state->redo_char_point += n;
STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
IMSTB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((IMSTB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(IMSTB_TEXTEDIT_CHARTYPE)));
// adjust the position of all the other records to account for above memmove
for (i=state->redo_point; i < k; ++i)
if (state->undo_rec[i].char_storage >= 0)
@@ -1157,12 +1158,12 @@ static void stb_textedit_discard_redo(StbUndoState *state)
}
// now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
// [DEAR IMGUI]
size_t move_size = (size_t)((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
size_t move_size = (size_t)((IMSTB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
const char* buf_begin = (char*)state->undo_rec; (void)buf_begin;
const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end;
IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin);
IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end);
STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size);
IMSTB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size);
// now move redo_point to point to the new one
++state->redo_point;
@@ -1176,32 +1177,32 @@ static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numch
// if we have no free records, we have to make room, by sliding the
// existing records down
if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
if (state->undo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
stb_textedit_discard_undo(state);
// if the characters to store won't possibly fit in the buffer, we can't undo
if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) {
if (numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT) {
state->undo_point = 0;
state->undo_char_point = 0;
return NULL;
}
// if we don't have enough free characters in the buffer, we have to make room
while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT)
while (state->undo_char_point + numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT)
stb_textedit_discard_undo(state);
return &state->undo_rec[state->undo_point++];
}
static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
static IMSTB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
{
StbUndoRecord *r = stb_text_create_undo_record(state, insert_len);
if (r == NULL)
return NULL;
r->where = pos;
r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len;
r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len;
r->insert_length = (IMSTB_TEXTEDIT_POSITIONTYPE) insert_len;
r->delete_length = (IMSTB_TEXTEDIT_POSITIONTYPE) delete_len;
if (insert_len == 0) {
r->char_storage = -1;
@@ -1213,7 +1214,7 @@ static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos,
}
}
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
StbUndoState *s = &state->undostate;
StbUndoRecord u, *r;
@@ -1240,7 +1241,7 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
// characters stored for *undoing* don't leave room for redo
// if the last is true, we have to bail
if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) {
if (s->undo_char_point + u.delete_length >= IMSTB_TEXTEDIT_UNDOCHARCOUNT) {
// the undo records take up too much character space; there's no space to store the redo characters
r->insert_length = 0;
} else {
@@ -1249,7 +1250,7 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
// there's definitely room to store the characters eventually
while (s->undo_char_point + u.delete_length > s->redo_char_point) {
// should never happen:
if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
return;
// there's currently not enough room, so discard a redo record
stb_textedit_discard_redo(s);
@@ -1281,11 +1282,11 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
s->redo_point--;
}
static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
StbUndoState *s = &state->undostate;
StbUndoRecord *u, r;
if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
return;
// we need to do two things: apply the redo record, and create an undo record
@@ -1337,20 +1338,20 @@ static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int le
stb_text_createundo(&state->undostate, where, 0, length);
}
static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
{
int i;
STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);
IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);
if (p) {
for (i=0; i < length; ++i)
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
}
}
static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
{
int i;
STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);
IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);
if (p) {
for (i=0; i < old_length; ++i)
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
@@ -1362,8 +1363,8 @@ static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_lin
{
state->undostate.undo_point = 0;
state->undostate.undo_char_point = 0;
state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
state->undostate.redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT;
state->undostate.redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT;
state->select_end = state->select_start = 0;
state->cursor = 0;
state->has_preferred_x = 0;
@@ -1386,16 +1387,16 @@ static void stb_textedit_initialize_state(STB_TexteditState *state, int is_singl
#pragma GCC diagnostic ignored "-Wcast-qual"
#endif
static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len)
static int stb_textedit_paste(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE const *ctext, int len)
{
return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE *) ctext, len);
return stb_textedit_paste_internal(str, state, (IMSTB_TEXTEDIT_CHARTYPE *) ctext, len);
}
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop
#endif
#endif//STB_TEXTEDIT_IMPLEMENTATION
#endif//IMSTB_TEXTEDIT_IMPLEMENTATION
/*
------------------------------------------------------------------------------

View File

@@ -656,7 +656,7 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
// If skip != 0, this tells stb_truetype to skip any codepoints for which
// there is no corresponding glyph. If skip=0, which is the default, then
// codepoints without a glyph recived the font's "missing character" glyph,
// codepoints without a glyph received the font's "missing character" glyph,
// typically an empty box by convention.
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above

View File

@@ -11,7 +11,7 @@
// 2023/01/04: fixed a packing issue which in some occurrences would prevent large amount of glyphs from being packed correctly.
// 2021/08/23: fixed crash when FT_Render_Glyph() fails to render a glyph and returns NULL.
// 2021/03/05: added ImGuiFreeTypeBuilderFlags_Bitmap to load bitmap glyphs.
// 2021/03/02: set 'atlas->TexPixelsUseColors = true' to help some backends with deciding of a prefered texture format.
// 2021/03/02: set 'atlas->TexPixelsUseColors = true' to help some backends with deciding of a preferred texture format.
// 2021/01/28: added support for color-layered glyphs via ImGuiFreeTypeBuilderFlags_LoadColor (require Freetype 2.10+).
// 2021/01/26: simplified integration by using '#define IMGUI_ENABLE_FREETYPE'. renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API. removed ImGuiFreeType::BuildFontAtlas().
// 2020/06/04: fix for rare case where FT_Get_Char_Index() succeed but FT_Load_Glyph() fails.
@@ -437,7 +437,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
ImFontAtlasBuildInit(atlas);
// Clear atlas
atlas->TexID = (ImTextureID)nullptr;
atlas->TexID = 0;
atlas->TexWidth = atlas->TexHeight = 0;
atlas->TexUvScale = ImVec2(0.0f, 0.0f);
atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f);

View File

@@ -43,9 +43,8 @@ namespace ImGuiFreeType
IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = nullptr);
// Obsolete names (will be removed soon)
// Prefer using '#define IMGUI_ENABLE_FREETYPE'
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontBuilderFlags = flags; return atlas->Build(); }
//static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontBuilderFlags = flags; return atlas->Build(); } // Prefer using '#define IMGUI_ENABLE_FREETYPE'
#endif
}