Compare commits

..

219 Commits

Author SHA1 Message Date
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
62 changed files with 3275 additions and 1754 deletions

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

View File

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

View File

@@ -1,6 +1,6 @@
The MIT License (MIT) 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal 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: 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-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. // 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-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-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) // 2021-05-19: Renderer: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)

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(); ImGuiIO& io = ImGui::GetIO();
int32_t event_type = AInputEvent_getType(input_event); 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: case AKEY_EVENT_ACTION_UP:
{ {
ImGuiKey key = ImGui_ImplAndroid_KeyCodeToImGuiKey(event_key_code); 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.AddKeyEvent(key, event_action == AKEY_EVENT_ACTION_DOWN);
io.SetKeyEventNativeData(key, event_key_code, event_scan_code); 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_DOWN:
case AMOTION_EVENT_ACTION_UP: case AMOTION_EVENT_ACTION_UP:
{
// Physical mouse buttons (and probably other physical devices) also invoke the actions AMOTION_EVENT_ACTION_DOWN/_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 // 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). // 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) int tool_type = AMotionEvent_getToolType(input_event, event_pointer_index);
|| (AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_UNKNOWN)) 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.AddMousePosEvent(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
io.AddMouseButtonEvent(0, event_action == AMOTION_EVENT_ACTION_DOWN); io.AddMouseButtonEvent(0, event_action == AMOTION_EVENT_ACTION_DOWN);
} }
break; break;
}
case AMOTION_EVENT_ACTION_BUTTON_PRESS: case AMOTION_EVENT_ACTION_BUTTON_PRESS:
case AMOTION_EVENT_ACTION_BUTTON_RELEASE: case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
{ {
int32_t button_state = AMotionEvent_getButtonState(input_event); int32_t button_state = AMotionEvent_getButtonState(input_event);
io.AddMouseButtonEvent(0, (button_state & AMOTION_EVENT_BUTTON_PRIMARY) != 0); io.AddMouseButtonEvent(0, (button_state & AMOTION_EVENT_BUTTON_PRIMARY) != 0);
io.AddMouseButtonEvent(1, (button_state & AMOTION_EVENT_BUTTON_SECONDARY) != 0); io.AddMouseButtonEvent(1, (button_state & AMOTION_EVENT_BUTTON_SECONDARY) != 0);
io.AddMouseButtonEvent(2, (button_state & AMOTION_EVENT_BUTTON_TERTIARY) != 0); io.AddMouseButtonEvent(2, (button_state & AMOTION_EVENT_BUTTON_TERTIARY) != 0);
}
break; break;
}
case AMOTION_EVENT_ACTION_HOVER_MOVE: // Hovering: Tool moves while NOT pressed (such as a physical mouse) 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 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)); io.AddMousePosEvent(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));

View File

@@ -30,7 +30,7 @@ struct ANativeWindow;
struct AInputEvent; struct AInputEvent;
IMGUI_IMPL_API bool ImGui_ImplAndroid_Init(ANativeWindow* window); 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_Shutdown();
IMGUI_IMPL_API void ImGui_ImplAndroid_NewFrame(); IMGUI_IMPL_API void ImGui_ImplAndroid_NewFrame();

View File

@@ -16,7 +16,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (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. // 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-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) // 2021-05-19: DirectX10: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)

View File

@@ -16,7 +16,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (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. // 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-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) // 2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)

View File

@@ -25,7 +25,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (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. // 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-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) // 2021-05-19: DirectX12: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
@@ -899,7 +899,7 @@ static void ImGui_ImplDX12_CreateWindow(ImGuiViewport* viewport)
sd1.SampleDesc.Quality = 0; sd1.SampleDesc.Quality = 0;
sd1.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; sd1.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
sd1.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; sd1.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
sd1.Scaling = DXGI_SCALING_STRETCH; sd1.Scaling = DXGI_SCALING_NONE;
sd1.Stereo = FALSE; sd1.Stereo = FALSE;
IDXGIFactory4* dxgi_factory = nullptr; IDXGIFactory4* dxgi_factory = nullptr;

View File

@@ -16,7 +16,8 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (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. // 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-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. // 2021-06-25: DirectX9: Explicitly disable texture state stages after >= 1.
@@ -330,6 +331,24 @@ void ImGui_ImplDX9_Shutdown()
IM_DELETE(bd); 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() static bool ImGui_ImplDX9_CreateFontsTexture()
{ {
// Build texture atlas // Build texture atlas
@@ -341,18 +360,21 @@ static bool ImGui_ImplDX9_CreateFontsTexture()
// Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices) // Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices)
#ifndef IMGUI_USE_BGRA_PACKED_COLOR #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); 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++) 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); *dst = IMGUI_COL_TO_DX9_ARGB(*src);
pixels = (unsigned char*)dst_start; pixels = (unsigned char*)dst_start;
} }
#else
const bool rgba_support = false;
#endif #endif
// Upload texture to graphics system // Upload texture to graphics system
bd->FontTexture = nullptr; 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; return false;
D3DLOCKED_RECT tex_locked_rect; D3DLOCKED_RECT tex_locked_rect;
if (bd->FontTexture->LockRect(0, &tex_locked_rect, nullptr, 0) != D3D_OK) if (bd->FontTexture->LockRect(0, &tex_locked_rect, nullptr, 0) != D3D_OK)
@@ -365,7 +387,7 @@ static bool ImGui_ImplDX9_CreateFontsTexture()
io.Fonts->SetTexID((ImTextureID)bd->FontTexture); io.Fonts->SetTexID((ImTextureID)bd->FontTexture);
#ifndef IMGUI_USE_BGRA_PACKED_COLOR #ifndef IMGUI_USE_BGRA_PACKED_COLOR
if (io.Fonts->TexPixelsUseColors) if (!rgba_support && io.Fonts->TexPixelsUseColors)
ImGui::MemFree(pixels); ImGui::MemFree(pixels);
#endif #endif

View File

@@ -24,7 +24,8 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (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-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-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) // 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)
@@ -137,7 +138,7 @@ enum GlfwClientApi
{ {
GlfwClientApi_Unknown, GlfwClientApi_Unknown,
GlfwClientApi_OpenGL, GlfwClientApi_OpenGL,
GlfwClientApi_Vulkan GlfwClientApi_Vulkan,
}; };
struct ImGui_ImplGlfw_Data struct ImGui_ImplGlfw_Data
@@ -152,6 +153,9 @@ struct ImGui_ImplGlfw_Data
bool InstalledCallbacks; bool InstalledCallbacks;
bool CallbacksChainForAllWindows; bool CallbacksChainForAllWindows;
bool WantUpdateMonitors; bool WantUpdateMonitors;
#ifdef __EMSCRIPTEN__
const char* CanvasSelector;
#endif
// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
GLFWwindowfocusfun PrevUserCallbackWindowFocus; GLFWwindowfocusfun PrevUserCallbackWindowFocus;
@@ -577,7 +581,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
#ifndef __EMSCRIPTEN__ #ifndef __EMSCRIPTEN__
io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional) io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
#endif #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) io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can call io.AddMouseViewportEvent() with correct data (optional)
#endif #endif
@@ -644,9 +648,9 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
// Windows: register a WndProc hook so we can intercept some messages. // Windows: register a WndProc hook so we can intercept some messages.
#ifdef _WIN32 #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); 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 #endif
bd->ClientApi = client_api; bd->ClientApi = client_api;
@@ -688,7 +692,7 @@ void ImGui_ImplGlfw_Shutdown()
// Windows: restore our WndProc hook // Windows: restore our WndProc hook
#ifdef _WIN32 #ifdef _WIN32
ImGuiViewport* main_viewport = ImGui::GetMainViewport(); 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; bd->PrevWndProc = nullptr;
#endif #endif
@@ -704,7 +708,6 @@ static void ImGui_ImplGlfw_UpdateMouseData()
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGuiID mouse_viewport_id = 0; ImGuiID mouse_viewport_id = 0;
const ImVec2 mouse_pos_prev = io.MousePos; const ImVec2 mouse_pos_prev = io.MousePos;
for (int n = 0; n < platform_io.Viewports.Size; n++) for (int n = 0; n < platform_io.Viewports.Size; n++)
@@ -745,7 +748,8 @@ static void ImGui_ImplGlfw_UpdateMouseData()
// (Optional) When using multiple viewports: call io.AddMouseViewportEvent() with the viewport the OS mouse cursor is hovering. // (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. // 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. // - [!] 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 // 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 // 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 +757,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). // - [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. // 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. // 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 #if GLFW_HAS_MOUSE_PASSTHROUGH
const bool window_no_input = (viewport->Flags & ImGuiViewportFlags_NoInputs) != 0;
glfwSetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH, window_no_input); glfwSetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH, window_no_input);
#endif #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; mouse_viewport_id = viewport->ID;
#else #else
// We cannot use bd->MouseWindow maintained from CursorEnter/Leave callbacks, because it is locked to the window capturing mouse. // We cannot use bd->MouseWindow maintained from CursorEnter/Leave callbacks, because it is locked to the window capturing mouse.
@@ -923,6 +927,43 @@ void ImGui_ImplGlfw_NewFrame()
ImGui_ImplGlfw_UpdateGamepads(); 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 && "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 // MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously. // This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
@@ -1076,8 +1117,8 @@ static void ImGui_ImplGlfw_ShowWindow(ImGuiViewport* viewport)
// GLFW hack: install hook for WM_NCHITTEST message handler // GLFW hack: install hook for WM_NCHITTEST message handler
#if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED && defined(_WIN32) #if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED && defined(_WIN32)
::SetPropA(hwnd, "IMGUI_VIEWPORT", viewport); ::SetPropA(hwnd, "IMGUI_VIEWPORT", viewport);
vd->PrevWndProc = (WNDPROC)::GetWindowLongPtr(hwnd, GWLP_WNDPROC); vd->PrevWndProc = (WNDPROC)::GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
::SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc); ::SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
#endif #endif
#if !GLFW_HAS_FOCUS_ON_SHOW #if !GLFW_HAS_FOCUS_ON_SHOW
@@ -1264,7 +1305,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 #ifdef _WIN32
static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo() static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo()
{ {
@@ -1311,7 +1352,7 @@ static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wPara
} }
#endif #endif
} }
return ::CallWindowProc(prev_wndproc, hWnd, msg, wParam, lParam); return ::CallWindowProcW(prev_wndproc, hWnd, msg, wParam, lParam);
} }
#endif // #ifdef _WIN32 #endif // #ifdef _WIN32

View File

@@ -35,6 +35,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_Shutdown();
IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame(); 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 // 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=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. // - 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

@@ -16,7 +16,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (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-08-23: Metal: Update deprecated property 'sampleCount'->'rasterSampleCount'.
// 2022-07-05: Metal: Add dispatch synchronization. // 2022-07-05: Metal: Add dispatch synchronization.
// 2022-06-30: Metal: Use __bridge for ARC based systems. // 2022-06-30: Metal: Use __bridge for ARC based systems.

View File

@@ -23,9 +23,9 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (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. // 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-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-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. // 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.

View File

@@ -23,8 +23,9 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (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-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-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-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-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) // 2023-05-09: OpenGL: Support for glBindSampler() backup/restore on ES3. (#6375)
@@ -177,9 +178,20 @@
#define GL_VERTEX_ARRAY_BINDING GL_VERTEX_ARRAY_BINDING_OES #define GL_VERTEX_ARRAY_BINDING GL_VERTEX_ARRAY_BINDING_OES
#endif #endif
// Desktop GL 2.0+ has glPolygonMode() which GL ES and WebGL don't have. // Desktop GL 2.0+ has extension and glPolygonMode() which GL ES and WebGL don't have..
#ifdef GL_POLYGON_MODE #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3)
#define IMGUI_IMPL_HAS_POLYGON_MODE #define IMGUI_IMPL_OPENGL_HAS_EXTENSIONS // has glGetIntegerv(GL_NUM_EXTENSIONS)
#define IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE // has 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 #endif
// Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have. // Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have.
@@ -192,16 +204,6 @@
#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER #define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
#endif #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] // [Debugging]
//#define IMGUI_IMPL_OPENGL_DEBUG //#define IMGUI_IMPL_OPENGL_DEBUG
#ifdef IMGUI_IMPL_OPENGL_DEBUG #ifdef IMGUI_IMPL_OPENGL_DEBUG
@@ -365,7 +367,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
// Detect extensions we support // Detect extensions we support
bd->HasClipOrigin = (bd->GlVersion >= 450); bd->HasClipOrigin = (bd->GlVersion >= 450);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS #ifdef IMGUI_IMPL_OPENGL_HAS_EXTENSIONS
GLint num_extensions = 0; GLint num_extensions = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
for (GLint i = 0; i < num_extensions; i++) for (GLint i = 0; i < num_extensions; i++)
@@ -421,7 +423,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
if (bd->GlVersion >= 310) if (bd->GlVersion >= 310)
glDisable(GL_PRIMITIVE_RESTART); glDisable(GL_PRIMITIVE_RESTART);
#endif #endif
#ifdef IMGUI_IMPL_HAS_POLYGON_MODE #ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif #endif
@@ -510,7 +512,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object); GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object);
#endif #endif
#ifdef IMGUI_IMPL_HAS_POLYGON_MODE #ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
#endif #endif
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
@@ -649,7 +651,7 @@ 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); } if (bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); }
#endif #endif
#ifdef IMGUI_IMPL_HAS_POLYGON_MODE #ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE
// Desktop OpenGL 3.0 and OpenGL 3.1 had separate polygon draw modes for front-facing and back-facing faces of polygons // 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) if (bd->GlVersion <= 310 || bd->GlProfileIsCompat)
{ {
@@ -660,7 +662,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
{ {
glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
} }
#endif // IMGUI_IMPL_HAS_POLYGON_MODE #endif // IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); 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]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
@@ -757,6 +759,10 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
GLint last_texture, last_array_buffer; GLint last_texture, last_array_buffer;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK
GLint last_pixel_unpack_buffer;
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 #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
GLint last_vertex_array; GLint last_vertex_array;
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
@@ -930,6 +936,9 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
// Restore modified GL state // Restore modified GL state
glBindTexture(GL_TEXTURE_2D, last_texture); glBindTexture(GL_TEXTURE_2D, last_texture);
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); 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 #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
glBindVertexArray(last_vertex_array); glBindVertexArray(last_vertex_array);
#endif #endif

View File

@@ -260,6 +260,8 @@ typedef khronos_intptr_t GLintptr;
#define GL_ARRAY_BUFFER_BINDING 0x8894 #define GL_ARRAY_BUFFER_BINDING 0x8894
#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 #define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
#define GL_STREAM_DRAW 0x88E0 #define GL_STREAM_DRAW 0x88E0
#define GL_PIXEL_UNPACK_BUFFER 0x88EC
#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
@@ -608,7 +610,7 @@ extern "C" {
#include <stdlib.h> #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) #if defined(_WIN32)
#ifndef WIN32_LEAN_AND_MEAN #ifndef WIN32_LEAN_AND_MEAN
@@ -668,6 +670,10 @@ static int open_libgl(void)
{ {
// While most systems use libGL.so.1, NetBSD seems to use that libGL.so.3. See https://github.com/ocornut/imgui/issues/6983 // 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); 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) if (!libgl)
return GL3W_ERROR_LIBRARY_OPEN; return GL3W_ERROR_LIBRARY_OPEN;
*(void **)(&glx_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB"); *(void **)(&glx_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB");
@@ -800,7 +806,7 @@ GL3W_API union ImGL3WProcs imgl3wProcs;
static void load_procs(GL3WGetProcAddressProc proc) static void load_procs(GL3WGetProcAddressProc proc)
{ {
size_t i; 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]); imgl3wProcs.ptr[i] = proc(proc_names[i]);
} }

View File

@@ -10,7 +10,8 @@
// [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend). // [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: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: IME support. // [X] Platform: IME support.
// [X] Platform: Multi-viewport / platform windows. // [x] Platform: Multi-viewport / platform windows.
// - [ ] Window size not correctly reported when enabling io.ConfigViewportsNoDecoration
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // 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. // 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,8 @@
// [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend). // [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: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: IME support. // [X] Platform: IME support.
// [X] Platform: Multi-viewport / platform windows. // [x] Platform: Multi-viewport / platform windows.
// - [ ] Window size not correctly reported when enabling io.ConfigViewportsNoDecoration
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // 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. // 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 +31,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (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-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-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). // 2023-02-01: Fixed scroll wheel scaling for devices emitting events with hasPreciseScrollingDeltas==false (e.g. non-Apple mices).
@@ -140,12 +141,28 @@ static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view);
- (void)updateImePosWithView:(NSView *)view - (void)updateImePosWithView:(NSView *)view
{ {
NSWindow *window = view.window; NSWindow* window = view.window;
if (!window) if (!window)
return; return;
NSRect contentRect = [window contentRectForFrameRect:window.frame];
NSRect rect = NSMakeRect(_posX, contentRect.size.height - _posY, 0, 0); ImGuiIO& io = ImGui::GetIO();
_imeRect = [window convertRectToScreen:rect]; 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 - (void)viewDidMoveToWindow
@@ -418,6 +435,7 @@ bool ImGui_ImplOSX_Init(NSView* view)
bd->Window = view.window ?: NSApp.orderedWindows.firstObject; bd->Window = view.window ?: NSApp.orderedWindows.firstObject;
ImGuiViewport* main_viewport = ImGui::GetMainViewport(); ImGuiViewport* main_viewport = ImGui::GetMainViewport();
main_viewport->PlatformHandle = main_viewport->PlatformHandleRaw = (__bridge_retained void*)bd->Window; main_viewport->PlatformHandle = main_viewport->PlatformHandleRaw = (__bridge_retained void*)bd->Window;
ImGui_ImplOSX_UpdateMonitors();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplOSX_InitPlatformInterface(); ImGui_ImplOSX_InitPlatformInterface();
@@ -553,7 +571,6 @@ static void ImGui_ImplOSX_UpdateMouseCursor()
static void ImGui_ImplOSX_UpdateGamepads() static void ImGui_ImplOSX_UpdateGamepads()
{ {
ImGuiIO& io = ImGui::GetIO(); 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. if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
return; return;
@@ -862,9 +879,11 @@ struct ImGuiViewportDataOSX
@end @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) static void ImGui_ImplOSX_CreateWindow(ImGuiViewport* viewport)
@@ -875,7 +894,7 @@ static void ImGui_ImplOSX_CreateWindow(ImGuiViewport* viewport)
NSScreen* screen = bd->Window.screen; NSScreen* screen = bd->Window.screen;
NSRect rect = NSMakeRect(viewport->Pos.x, viewport->Pos.y, viewport->Size.x, viewport->Size.y); NSRect rect = NSMakeRect(viewport->Pos.x, viewport->Pos.y, viewport->Size.x, viewport->Size.y);
ConvertNSRect(screen, &rect); ConvertNSRect(&rect);
NSWindowStyleMask styleMask = 0; NSWindowStyleMask styleMask = 0;
if (viewport->Flags & ImGuiViewportFlags_NoDecoration) if (viewport->Flags & ImGuiViewportFlags_NoDecoration)
@@ -945,11 +964,13 @@ static ImVec2 ImGui_ImplOSX_GetWindowPos(ImGuiViewport* viewport)
IM_ASSERT(data->Window != 0); IM_ASSERT(data->Window != 0);
NSWindow* window = data->Window; NSWindow* window = data->Window;
NSScreen* screen = window.screen;
NSSize size = screen.frame.size;
NSRect frame = window.frame; NSRect frame = window.frame;
NSRect rect = window.contentLayoutRect; NSRect contentRect = window.contentLayoutRect;
return ImVec2(frame.origin.x, size.height - frame.origin.y - rect.size.height); 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) static void ImGui_ImplOSX_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos)
@@ -961,7 +982,7 @@ static void ImGui_ImplOSX_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos)
NSSize size = window.frame.size; NSSize size = window.frame.size;
NSRect r = NSMakeRect(pos.x, pos.y, size.width, size.height); NSRect r = NSMakeRect(pos.x, pos.y, size.width, size.height);
ConvertNSRect(window.screen, &r); ConvertNSRect(&r);
[window setFrameOrigin:r.origin]; [window setFrameOrigin:r.origin];
} }
@@ -1042,10 +1063,15 @@ static void ImGui_ImplOSX_UpdateMonitors()
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Monitors.resize(0); 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) for (NSScreen* screen in NSScreen.screens)
{ {
NSRect frame = screen.frame; NSRect frame = screen.frame;
NSRect visibleFrame = screen.visibleFrame; NSRect visibleFrame = screen.visibleFrame;
ConvertNSRect(&frame);
ConvertNSRect(&visibleFrame);
ImGuiPlatformMonitor imgui_monitor; ImGuiPlatformMonitor imgui_monitor;
imgui_monitor.MainPos = ImVec2(frame.origin.x, frame.origin.y); imgui_monitor.MainPos = ImVec2(frame.origin.x, frame.origin.y);
@@ -1062,7 +1088,6 @@ static void ImGui_ImplOSX_UpdateMonitors()
static void ImGui_ImplOSX_InitPlatformInterface() static void ImGui_ImplOSX_InitPlatformInterface()
{ {
ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData();
ImGui_ImplOSX_UpdateMonitors();
// Register platform interface (will be coupled with a renderer interface) // Register platform interface (will be coupled with a renderer interface)
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();

View File

@@ -24,7 +24,8 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (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-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-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) // 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen. (#2702)
@@ -116,19 +117,26 @@ static const Uint32 SDL_WINDOW_VULKAN = 0x10000000;
// SDL Data // SDL Data
struct ImGui_ImplSDL2_Data struct ImGui_ImplSDL2_Data
{ {
SDL_Window* Window; SDL_Window* Window;
SDL_Renderer* Renderer; SDL_Renderer* Renderer;
Uint64 Time; Uint64 Time;
Uint32 MouseWindowID; char* ClipboardTextData;
int MouseButtonsDown; bool UseVulkan;
SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT]; bool WantUpdateMonitors;
SDL_Cursor* LastMouseCursor;
int PendingMouseLeaveFrame; // Mouse handling
char* ClipboardTextData; Uint32 MouseWindowID;
bool MouseCanUseGlobalState; int MouseButtonsDown;
bool MouseCanReportHoveredViewport; // This is hard to use/unreliable on SDL so we'll set ImGuiBackendFlags_HasMouseHoveredViewport dynamically based on state. SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT];
bool UseVulkan; SDL_Cursor* MouseLastCursor;
bool WantUpdateMonitors; 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)); } ImGui_ImplSDL2_Data() { memset((void*)this, 0, sizeof(*this)); }
}; };
@@ -405,10 +413,10 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
if (window_event == SDL_WINDOWEVENT_ENTER) if (window_event == SDL_WINDOWEVENT_ENTER)
{ {
bd->MouseWindowID = event->window.windowID; bd->MouseWindowID = event->window.windowID;
bd->PendingMouseLeaveFrame = 0; bd->MouseLastLeaveFrame = 0;
} }
if (window_event == SDL_WINDOWEVENT_LEAVE) if (window_event == SDL_WINDOWEVENT_LEAVE)
bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1; bd->MouseLastLeaveFrame = ImGui::GetFrameCount() + 1;
if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED) if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED)
io.AddFocusEvent(true); io.AddFocusEvent(true);
else if (window_event == SDL_WINDOWEVENT_FOCUS_LOST) else if (window_event == SDL_WINDOWEVENT_FOCUS_LOST)
@@ -426,6 +434,12 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
} }
return true; return true;
} }
case SDL_CONTROLLERDEVICEADDED:
case SDL_CONTROLLERDEVICEREMOVED:
{
bd->WantUpdateGamepadsList = true;
return true;
}
} }
return false; return false;
} }
@@ -473,6 +487,10 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void
io.ClipboardUserData = nullptr; io.ClipboardUserData = nullptr;
io.SetPlatformImeDataFn = ImGui_ImplSDL2_SetPlatformImeData; io.SetPlatformImeDataFn = ImGui_ImplSDL2_SetPlatformImeData;
// Gamepad handling
bd->GamepadMode = ImGui_ImplSDL2_GamepadMode_AutoFirst;
bd->WantUpdateGamepadsList = true;
// Load mouse cursors // Load mouse cursors
bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
@@ -569,6 +587,8 @@ bool ImGui_ImplSDL2_InitForOther(SDL_Window* window)
return ImGui_ImplSDL2_Init(window, nullptr, nullptr); return ImGui_ImplSDL2_Init(window, nullptr, nullptr);
} }
static void ImGui_ImplSDL2_CloseGamepads();
void ImGui_ImplSDL2_Shutdown() void ImGui_ImplSDL2_Shutdown()
{ {
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
@@ -581,7 +601,7 @@ void ImGui_ImplSDL2_Shutdown()
SDL_free(bd->ClipboardTextData); SDL_free(bd->ClipboardTextData);
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
SDL_FreeCursor(bd->MouseCursors[cursor_n]); SDL_FreeCursor(bd->MouseCursors[cursor_n]);
bd->LastMouseCursor = nullptr; ImGui_ImplSDL2_CloseGamepads();
io.BackendPlatformName = nullptr; io.BackendPlatformName = nullptr;
io.BackendPlatformUserData = nullptr; io.BackendPlatformUserData = nullptr;
@@ -670,59 +690,118 @@ static void ImGui_ImplSDL2_UpdateMouseCursor()
{ {
// Show OS mouse cursor // Show OS mouse cursor
SDL_Cursor* expected_cursor = bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]; 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) 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); 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() static void ImGui_ImplSDL2_UpdateGamepads()
{ {
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
ImGuiIO& io = ImGui::GetIO(); 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; io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
SDL_GameController* game_controller = SDL_GameControllerOpen(0); if (bd->Gamepads.Size == 0)
if (!game_controller)
return; return;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad; io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
// Update gamepad inputs // Update gamepad inputs
#define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V) const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value.
#define MAP_BUTTON(KEY_NO, BUTTON_NO) { io.AddKeyEvent(KEY_NO, SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0); } ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadStart, SDL_CONTROLLER_BUTTON_START);
#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); } ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadBack, SDL_CONTROLLER_BUTTON_BACK);
const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value. ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceLeft, SDL_CONTROLLER_BUTTON_X); // Xbox X, PS Square
MAP_BUTTON(ImGuiKey_GamepadStart, SDL_CONTROLLER_BUTTON_START); ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceRight, SDL_CONTROLLER_BUTTON_B); // Xbox B, PS Circle
MAP_BUTTON(ImGuiKey_GamepadBack, SDL_CONTROLLER_BUTTON_BACK); ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceUp, SDL_CONTROLLER_BUTTON_Y); // Xbox Y, PS Triangle
MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SDL_CONTROLLER_BUTTON_X); // Xbox X, PS Square ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceDown, SDL_CONTROLLER_BUTTON_A); // Xbox A, PS Cross
MAP_BUTTON(ImGuiKey_GamepadFaceRight, SDL_CONTROLLER_BUTTON_B); // Xbox B, PS Circle ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
MAP_BUTTON(ImGuiKey_GamepadFaceUp, SDL_CONTROLLER_BUTTON_Y); // Xbox Y, PS Triangle ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
MAP_BUTTON(ImGuiKey_GamepadFaceDown, SDL_CONTROLLER_BUTTON_A); // Xbox A, PS Cross ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP);
MAP_BUTTON(ImGuiKey_GamepadDpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT); ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
MAP_BUTTON(ImGuiKey_GamepadDpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadL1, SDL_CONTROLLER_BUTTON_LEFTSHOULDER);
MAP_BUTTON(ImGuiKey_GamepadDpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP); ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadR1, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
MAP_BUTTON(ImGuiKey_GamepadDpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN); ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadL2, SDL_CONTROLLER_AXIS_TRIGGERLEFT, 0.0f, 32767);
MAP_BUTTON(ImGuiKey_GamepadL1, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadR2, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 0.0f, 32767);
MAP_BUTTON(ImGuiKey_GamepadR1, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadL3, SDL_CONTROLLER_BUTTON_LEFTSTICK);
MAP_ANALOG(ImGuiKey_GamepadL2, SDL_CONTROLLER_AXIS_TRIGGERLEFT, 0.0f, 32767); ImGui_ImplSDL2_UpdateGamepadButton(bd, io, ImGuiKey_GamepadR3, SDL_CONTROLLER_BUTTON_RIGHTSTICK);
MAP_ANALOG(ImGuiKey_GamepadR2, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 0.0f, 32767); ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768);
MAP_BUTTON(ImGuiKey_GamepadL3, SDL_CONTROLLER_BUTTON_LEFTSTICK); ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767);
MAP_BUTTON(ImGuiKey_GamepadR3, SDL_CONTROLLER_BUTTON_RIGHTSTICK); ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadLStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768); ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadLStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767); ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickLeft, SDL_CONTROLLER_AXIS_RIGHTX, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadLStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32768); ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickRight, SDL_CONTROLLER_AXIS_RIGHTX, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadLStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767); ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickUp, SDL_CONTROLLER_AXIS_RIGHTY, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadRStickLeft, SDL_CONTROLLER_AXIS_RIGHTX, -thumb_dead_zone, -32768); ImGui_ImplSDL2_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickDown, SDL_CONTROLLER_AXIS_RIGHTY, +thumb_dead_zone, +32767);
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
} }
// FIXME: Note that doesn't update with DPI/Scaling change only as SDL2 doesn't have an event for it (SDL3 has). // FIXME: Note that doesn't update with DPI/Scaling change only as SDL2 doesn't have an event for it (SDL3 has).
@@ -791,10 +870,10 @@ void ImGui_ImplSDL2_NewFrame()
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f); io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f);
bd->Time = current_time; 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->MouseWindowID = 0;
bd->PendingMouseLeaveFrame = 0; bd->MouseLastLeaveFrame = 0;
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
} }

View File

@@ -27,6 +27,7 @@
struct SDL_Window; struct SDL_Window;
struct SDL_Renderer; struct SDL_Renderer;
struct _SDL_GameController;
typedef union SDL_Event SDL_Event; typedef union SDL_Event SDL_Event;
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context); IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context);
@@ -39,8 +40,9 @@ IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown();
IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame(); IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame();
IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event); IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event);
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // Gamepad selection automatically starts in AutoFirst mode, picking first available SDL_Gamepad. You may override this.
static inline void ImGui_ImplSDL2_NewFrame(SDL_Window*) { ImGui_ImplSDL2_NewFrame(); } // 1.84: removed unnecessary parameter // When using manual mode, caller is responsible for opening/closing gamepad.
#endif 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 #endif // #ifndef IMGUI_DISABLE

View File

@@ -24,7 +24,8 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (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-13: Inputs: Fixed gamepad support. Handle gamepad disconnection. Added ImGui_ImplSDL3_SetGamepadMode().
// 2023-11-13: Updated for recent SDL3 API changes. // 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-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) // 2023-05-04: Fixed build on Emscripten/iOS/Android. (#6391)
@@ -64,19 +65,26 @@
// SDL Data // SDL Data
struct ImGui_ImplSDL3_Data struct ImGui_ImplSDL3_Data
{ {
SDL_Window* Window; SDL_Window* Window;
SDL_Renderer* Renderer; SDL_Renderer* Renderer;
Uint64 Time; Uint64 Time;
Uint32 MouseWindowID; char* ClipboardTextData;
int MouseButtonsDown; bool UseVulkan;
SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT]; bool WantUpdateMonitors;
SDL_Cursor* LastMouseCursor;
int PendingMouseLeaveFrame; // Mouse handling
char* ClipboardTextData; Uint32 MouseWindowID;
bool MouseCanUseGlobalState; int MouseButtonsDown;
bool MouseCanReportHoveredViewport; // This is hard to use/unreliable on SDL so we'll set ImGuiBackendFlags_HasMouseHoveredViewport dynamically based on state. SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT];
bool UseVulkan; SDL_Cursor* MouseLastCursor;
bool WantUpdateMonitors; 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)); } ImGui_ImplSDL3_Data() { memset((void*)this, 0, sizeof(*this)); }
}; };
@@ -339,7 +347,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
case SDL_EVENT_WINDOW_MOUSE_ENTER: case SDL_EVENT_WINDOW_MOUSE_ENTER:
{ {
bd->MouseWindowID = event->window.windowID; bd->MouseWindowID = event->window.windowID;
bd->PendingMouseLeaveFrame = 0; bd->MousePendingLeaveFrame = 0;
return true; return true;
} }
// - In some cases, when detaching a window from main viewport SDL may send SDL_WINDOWEVENT_ENTER one frame too late, // - In some cases, when detaching a window from main viewport SDL may send SDL_WINDOWEVENT_ENTER one frame too late,
@@ -348,7 +356,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
// FIXME: Unconfirmed whether this is still needed with SDL3. // FIXME: Unconfirmed whether this is still needed with SDL3.
case SDL_EVENT_WINDOW_MOUSE_LEAVE: case SDL_EVENT_WINDOW_MOUSE_LEAVE:
{ {
bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1; bd->MousePendingLeaveFrame = ImGui::GetFrameCount() + 1;
return true; return true;
} }
case SDL_EVENT_WINDOW_FOCUS_GAINED: case SDL_EVENT_WINDOW_FOCUS_GAINED:
@@ -371,6 +379,12 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
return true; return true;
} }
return true; return true;
case SDL_EVENT_GAMEPAD_ADDED:
case SDL_EVENT_GAMEPAD_REMOVED:
{
bd->WantUpdateGamepadsList = true;
return true;
}
} }
return false; return false;
} }
@@ -380,9 +394,9 @@ static void ImGui_ImplSDL3_SetupPlatformHandles(ImGuiViewport* viewport, SDL_Win
viewport->PlatformHandle = window; viewport->PlatformHandle = window;
viewport->PlatformHandleRaw = nullptr; viewport->PlatformHandleRaw = nullptr;
#if defined(__WIN32__) && !defined(__WINRT__) #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) #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 #endif
} }
@@ -430,6 +444,10 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
io.ClipboardUserData = nullptr; io.ClipboardUserData = nullptr;
io.SetPlatformImeDataFn = ImGui_ImplSDL3_SetPlatformImeData; io.SetPlatformImeDataFn = ImGui_ImplSDL3_SetPlatformImeData;
// Gamepad handling
bd->GamepadMode = ImGui_ImplSDL3_GamepadMode_AutoFirst;
bd->WantUpdateGamepadsList = true;
// Load mouse cursors // Load mouse cursors
bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
@@ -504,6 +522,8 @@ bool ImGui_ImplSDL3_InitForOther(SDL_Window* window)
return ImGui_ImplSDL3_Init(window, nullptr, nullptr); return ImGui_ImplSDL3_Init(window, nullptr, nullptr);
} }
static void ImGui_ImplSDL3_CloseGamepads();
void ImGui_ImplSDL3_Shutdown() void ImGui_ImplSDL3_Shutdown()
{ {
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
@@ -516,7 +536,7 @@ void ImGui_ImplSDL3_Shutdown()
SDL_free(bd->ClipboardTextData); SDL_free(bd->ClipboardTextData);
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
SDL_DestroyCursor(bd->MouseCursors[cursor_n]); SDL_DestroyCursor(bd->MouseCursors[cursor_n]);
bd->LastMouseCursor = nullptr; ImGui_ImplSDL3_CloseGamepads();
io.BackendPlatformName = nullptr; io.BackendPlatformName = nullptr;
io.BackendPlatformUserData = nullptr; io.BackendPlatformUserData = nullptr;
@@ -605,59 +625,118 @@ static void ImGui_ImplSDL3_UpdateMouseCursor()
{ {
// Show OS mouse cursor // Show OS mouse cursor
SDL_Cursor* expected_cursor = bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]; 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) 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_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() static void ImGui_ImplSDL3_UpdateGamepads()
{ {
ImGuiIO& io = ImGui::GetIO(); 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. ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
return;
// 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;
}
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; io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
SDL_Gamepad* gamepad = SDL_OpenGamepad(0); if (bd->Gamepads.Size == 0)
if (!gamepad)
return; return;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad; io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
// Update gamepad inputs // Update gamepad inputs
#define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V) const int thumb_dead_zone = 8000; // SDL_gamepad.h suggests using this value.
#define MAP_BUTTON(KEY_NO, BUTTON_NO) { io.AddKeyEvent(KEY_NO, SDL_GetGamepadButton(gamepad, BUTTON_NO) != 0); } ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadStart, SDL_GAMEPAD_BUTTON_START);
#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); } ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadBack, SDL_GAMEPAD_BUTTON_BACK);
const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value. ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceLeft, SDL_GAMEPAD_BUTTON_WEST); // Xbox X, PS Square
MAP_BUTTON(ImGuiKey_GamepadStart, SDL_GAMEPAD_BUTTON_START); ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceRight, SDL_GAMEPAD_BUTTON_EAST); // Xbox B, PS Circle
MAP_BUTTON(ImGuiKey_GamepadBack, SDL_GAMEPAD_BUTTON_BACK); ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceUp, SDL_GAMEPAD_BUTTON_NORTH); // Xbox Y, PS Triangle
MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SDL_GAMEPAD_BUTTON_WEST); // Xbox X, PS Square ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadFaceDown, SDL_GAMEPAD_BUTTON_SOUTH); // Xbox A, PS Cross
MAP_BUTTON(ImGuiKey_GamepadFaceRight, SDL_GAMEPAD_BUTTON_EAST); // Xbox B, PS Circle ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadLeft, SDL_GAMEPAD_BUTTON_DPAD_LEFT);
MAP_BUTTON(ImGuiKey_GamepadFaceUp, SDL_GAMEPAD_BUTTON_NORTH); // Xbox Y, PS Triangle ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadRight, SDL_GAMEPAD_BUTTON_DPAD_RIGHT);
MAP_BUTTON(ImGuiKey_GamepadFaceDown, SDL_GAMEPAD_BUTTON_SOUTH); // Xbox A, PS Cross ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadUp, SDL_GAMEPAD_BUTTON_DPAD_UP);
MAP_BUTTON(ImGuiKey_GamepadDpadLeft, SDL_GAMEPAD_BUTTON_DPAD_LEFT); ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadDpadDown, SDL_GAMEPAD_BUTTON_DPAD_DOWN);
MAP_BUTTON(ImGuiKey_GamepadDpadRight, SDL_GAMEPAD_BUTTON_DPAD_RIGHT); ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadL1, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER);
MAP_BUTTON(ImGuiKey_GamepadDpadUp, SDL_GAMEPAD_BUTTON_DPAD_UP); ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadR1, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER);
MAP_BUTTON(ImGuiKey_GamepadDpadDown, SDL_GAMEPAD_BUTTON_DPAD_DOWN); ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadL2, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0.0f, 32767);
MAP_BUTTON(ImGuiKey_GamepadL1, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER); ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadR2, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0.0f, 32767);
MAP_BUTTON(ImGuiKey_GamepadR1, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER); ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadL3, SDL_GAMEPAD_BUTTON_LEFT_STICK);
MAP_ANALOG(ImGuiKey_GamepadL2, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0.0f, 32767); ImGui_ImplSDL3_UpdateGamepadButton(bd, io, ImGuiKey_GamepadR3, SDL_GAMEPAD_BUTTON_RIGHT_STICK);
MAP_ANALOG(ImGuiKey_GamepadR2, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0.0f, 32767); ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickLeft, SDL_GAMEPAD_AXIS_LEFTX, -thumb_dead_zone, -32768);
MAP_BUTTON(ImGuiKey_GamepadL3, SDL_GAMEPAD_BUTTON_LEFT_STICK); ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickRight, SDL_GAMEPAD_AXIS_LEFTX, +thumb_dead_zone, +32767);
MAP_BUTTON(ImGuiKey_GamepadR3, SDL_GAMEPAD_BUTTON_RIGHT_STICK); ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickUp, SDL_GAMEPAD_AXIS_LEFTY, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadLStickLeft, SDL_GAMEPAD_AXIS_LEFTX, -thumb_dead_zone, -32768); ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadLStickDown, SDL_GAMEPAD_AXIS_LEFTY, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadLStickRight, SDL_GAMEPAD_AXIS_LEFTX, +thumb_dead_zone, +32767); ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickLeft, SDL_GAMEPAD_AXIS_RIGHTX, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadLStickUp, SDL_GAMEPAD_AXIS_LEFTY, -thumb_dead_zone, -32768); ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickRight, SDL_GAMEPAD_AXIS_RIGHTX, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadLStickDown, SDL_GAMEPAD_AXIS_LEFTY, +thumb_dead_zone, +32767); ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickUp, SDL_GAMEPAD_AXIS_RIGHTY, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadRStickLeft, SDL_GAMEPAD_AXIS_RIGHTX, -thumb_dead_zone, -32768); ImGui_ImplSDL3_UpdateGamepadAnalog(bd, io, ImGuiKey_GamepadRStickDown, SDL_GAMEPAD_AXIS_RIGHTY, +thumb_dead_zone, +32767);
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
} }
static void ImGui_ImplSDL3_UpdateMonitors() static void ImGui_ImplSDL3_UpdateMonitors()
@@ -719,10 +798,10 @@ void ImGui_ImplSDL3_NewFrame()
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f); io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f);
bd->Time = current_time; 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->MouseWindowID = 0;
bd->PendingMouseLeaveFrame = 0; bd->MousePendingLeaveFrame = 0;
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
} }

View File

@@ -28,6 +28,7 @@
struct SDL_Window; struct SDL_Window;
struct SDL_Renderer; struct SDL_Renderer;
struct SDL_Gamepad;
typedef union SDL_Event SDL_Event; typedef union SDL_Event SDL_Event;
IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForOpenGL(SDL_Window* window, void* sdl_gl_context); IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForOpenGL(SDL_Window* window, void* sdl_gl_context);
@@ -40,4 +41,9 @@ IMGUI_IMPL_API void ImGui_ImplSDL3_Shutdown();
IMGUI_IMPL_API void ImGui_ImplSDL3_NewFrame(); IMGUI_IMPL_API void ImGui_ImplSDL3_NewFrame();
IMGUI_IMPL_API bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event); 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 #endif // #ifndef IMGUI_DISABLE

View File

@@ -22,6 +22,7 @@
// - Introduction, links and more at the top of imgui.cpp // - Introduction, links and more at the top of imgui.cpp
// CHANGELOG // CHANGELOG
// 2024-02-12: Amend to query SDL_RenderViewportSet() and restore viewport accordingly.
// 2023-05-30: Initial version. // 2023-05-30: Initial version.
#include "imgui.h" #include "imgui.h"
@@ -131,10 +132,12 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data)
struct BackupSDLRendererState struct BackupSDLRendererState
{ {
SDL_Rect Viewport; SDL_Rect Viewport;
bool ViewportEnabled;
bool ClipEnabled; bool ClipEnabled;
SDL_Rect ClipRect; SDL_Rect ClipRect;
}; };
BackupSDLRendererState old = {}; BackupSDLRendererState old = {};
old.ViewportEnabled = SDL_RenderViewportSet(bd->SDLRenderer) == SDL_TRUE;
old.ClipEnabled = SDL_RenderClipEnabled(bd->SDLRenderer) == SDL_TRUE; old.ClipEnabled = SDL_RenderClipEnabled(bd->SDLRenderer) == SDL_TRUE;
SDL_GetRenderViewport(bd->SDLRenderer, &old.Viewport); SDL_GetRenderViewport(bd->SDLRenderer, &old.Viewport);
SDL_GetRenderClipRect(bd->SDLRenderer, &old.ClipRect); SDL_GetRenderClipRect(bd->SDLRenderer, &old.ClipRect);
@@ -180,11 +183,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data)
const float* xy = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, pos)); 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)); 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+ 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 // Bind texture, Draw
SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID(); SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID();
@@ -199,7 +198,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data)
} }
// Restore modified SDL_Renderer state // Restore modified SDL_Renderer state
SDL_SetRenderViewport(bd->SDLRenderer, &old.Viewport); SDL_SetRenderViewport(bd->SDLRenderer, old.ViewportEnabled ? &old.Viewport : nullptr);
SDL_SetRenderClipRect(bd->SDLRenderer, old.ClipEnabled ? &old.ClipRect : nullptr); SDL_SetRenderClipRect(bd->SDLRenderer, old.ClipEnabled ? &old.ClipRect : nullptr);
} }

View File

@@ -34,7 +34,14 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (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: *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. // 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 unecessary as we create and destroy those objects in the backend.
// ImGui_ImplVulkan_CreateFontsTexture() is automatically called by NewFrame() the first time. // ImGui_ImplVulkan_CreateFontsTexture() is automatically called by NewFrame() the first time.
@@ -80,85 +87,24 @@
#ifndef IMGUI_DISABLE #ifndef IMGUI_DISABLE
#include "imgui_impl_vulkan.h" #include "imgui_impl_vulkan.h"
#include <stdio.h> #include <stdio.h>
#ifndef IM_MAX
#define IM_MAX(A, B) (((A) >= (B)) ? (A) : (B))
#endif
// Visual Studio warnings // Visual Studio warnings
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning (disable: 4127) // condition expression is constant #pragma warning (disable: 4127) // condition expression is constant
#endif #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 // Forward Declarations
struct ImGui_ImplVulkan_FrameRenderBuffers;
struct ImGui_ImplVulkan_WindowRenderBuffers;
bool ImGui_ImplVulkan_CreateDeviceObjects(); bool ImGui_ImplVulkan_CreateDeviceObjects();
void ImGui_ImplVulkan_DestroyDeviceObjects(); 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_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_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_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_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); void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator);
@@ -250,12 +196,75 @@ IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_DEF)
#undef IMGUI_VULKAN_FUNC_DEF #undef IMGUI_VULKAN_FUNC_DEF
#endif // VK_NO_PROTOTYPES #endif // VK_NO_PROTOTYPES
#if defined(VK_VERSION_1_3) || defined(VK_KHR_dynamic_rendering) #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
#define IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
static PFN_vkCmdBeginRenderingKHR ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR; static PFN_vkCmdBeginRenderingKHR ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR;
static PFN_vkCmdEndRenderingKHR ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR; static PFN_vkCmdEndRenderingKHR ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR;
#endif #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
{
bool WindowOwned;
ImGui_ImplVulkanH_Window Window; // Used by secondary viewports only
ImGui_ImplVulkan_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;
VkDeviceSize BufferMemoryAlignment;
VkPipelineCreateFlags PipelineCreateFlags;
VkDescriptorSetLayout DescriptorSetLayout;
VkPipelineLayout PipelineLayout;
VkPipeline Pipeline;
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 // SHADERS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -264,7 +273,7 @@ static PFN_vkCmdEndRenderingKHR ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR;
static void ImGui_ImplVulkan_InitPlatformInterface(); static void ImGui_ImplVulkan_InitPlatformInterface();
static void ImGui_ImplVulkan_ShutdownPlatformInterface(); 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 // # glslangValidator -V -x -o glsl_shader.vert.u32 glsl_shader.vert
/* /*
#version 450 core #version 450 core
@@ -328,7 +337,7 @@ static uint32_t __glsl_shader_vert_spv[] =
0x0000002d,0x0000002c,0x000100fd,0x00010038 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 // # glslangValidator -V -x -o glsl_shader.frag.u32 glsl_shader.frag
/* /*
#version 450 core #version 450 core
@@ -403,7 +412,13 @@ static void check_vk_result(VkResult err)
v->CheckVkResultFn(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_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
@@ -413,10 +428,10 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory
if (buffer_memory != VK_NULL_HANDLE) if (buffer_memory != VK_NULL_HANDLE)
vkFreeMemory(v->Device, buffer_memory, v->Allocator); 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 = {}; VkBufferCreateInfo buffer_info = {};
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_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.usage = usage;
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &buffer); err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &buffer);
@@ -434,10 +449,10 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory
err = vkBindBufferMemory(v->Device, buffer, buffer_memory, 0); err = vkBindBufferMemory(v->Device, buffer, buffer_memory, 0);
check_vk_result(err); 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(); ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
@@ -498,23 +513,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. // 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; ImGui_ImplVulkan_ViewportData* viewport_renderer_data = (ImGui_ImplVulkan_ViewportData*)draw_data->OwnerViewport->RendererUserData;
IM_ASSERT(viewport_renderer_data != nullptr); 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) if (wrb->FrameRenderBuffers == nullptr)
{ {
wrb->Index = 0; wrb->Index = 0;
wrb->Count = v->ImageCount; wrb->Count = v->ImageCount;
wrb->FrameRenderBuffers = (ImGui_ImplVulkanH_FrameRenderBuffers*)IM_ALLOC(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_ImplVulkanH_FrameRenderBuffers) * wrb->Count); memset(wrb->FrameRenderBuffers, 0, sizeof(ImGui_ImplVulkan_FrameRenderBuffers) * wrb->Count);
} }
IM_ASSERT(wrb->Count == v->ImageCount); IM_ASSERT(wrb->Count == v->ImageCount);
wrb->Index = (wrb->Index + 1) % wrb->Count; 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) if (draw_data->TotalVtxCount > 0)
{ {
// Create or resize the vertex/index buffers // Create or resize the vertex/index buffers
size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert); size_t vertex_size = AlignBufferSize(draw_data->TotalVtxCount * sizeof(ImDrawVert), bd->BufferMemoryAlignment);
size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); size_t index_size = AlignBufferSize(draw_data->TotalIdxCount * sizeof(ImDrawIdx), bd->BufferMemoryAlignment);
if (rb->VertexBuffer == VK_NULL_HANDLE || rb->VertexBufferSize < vertex_size) 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); 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) if (rb->IndexBuffer == VK_NULL_HANDLE || rb->IndexBufferSize < index_size)
@@ -523,9 +538,9 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
// Upload vertex/index data into a single contiguous GPU buffer // Upload vertex/index data into a single contiguous GPU buffer
ImDrawVert* vtx_dst = nullptr; ImDrawVert* vtx_dst = nullptr;
ImDrawIdx* idx_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); 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); check_vk_result(err);
for (int n = 0; n < draw_data->CmdListsCount; n++) for (int n = 0; n < draw_data->CmdListsCount; n++)
{ {
@@ -644,9 +659,9 @@ bool ImGui_ImplVulkan_CreateFontsTexture()
{ {
VkCommandPoolCreateInfo info = {}; VkCommandPoolCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_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; 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) if (bd->FontCommandBuffer == VK_NULL_HANDLE)
{ {
@@ -696,7 +711,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture()
vkGetImageMemoryRequirements(v->Device, bd->FontImage, &req); vkGetImageMemoryRequirements(v->Device, bd->FontImage, &req);
VkMemoryAllocateInfo alloc_info = {}; VkMemoryAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_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); alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits);
err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &bd->FontMemory); err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &bd->FontMemory);
check_vk_result(err); check_vk_result(err);
@@ -737,7 +752,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture()
bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->BufferMemoryAlignment : req.alignment; bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->BufferMemoryAlignment : req.alignment;
VkMemoryAllocateInfo alloc_info = {}; VkMemoryAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_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); 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); err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &upload_buffer_memory);
check_vk_result(err); check_vk_result(err);
@@ -811,7 +826,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture()
err = vkQueueSubmit(v->Queue, 1, &end_info, VK_NULL_HANDLE); err = vkQueueSubmit(v->Queue, 1, &end_info, VK_NULL_HANDLE);
check_vk_result(err); check_vk_result(err);
err = vkDeviceWaitIdle(v->Device); err = vkQueueWaitIdle(v->Queue);
check_vk_result(err); check_vk_result(err);
vkDestroyBuffer(v->Device, upload_buffer, v->Allocator); vkDestroyBuffer(v->Device, upload_buffer, v->Allocator);
@@ -965,13 +980,11 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC
info.subpass = subpass; info.subpass = subpass;
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING #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) 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. info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr.
} }
#endif #endif
@@ -1036,7 +1049,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
check_vk_result(err); 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; return true;
} }
@@ -1048,6 +1061,7 @@ void ImGui_ImplVulkan_DestroyDeviceObjects()
ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(v->Device, v->Allocator); ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(v->Device, v->Allocator);
ImGui_ImplVulkan_DestroyFontsTexture(); 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->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->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; } if (bd->ShaderModuleFrag) { vkDestroyShaderModule(v->Device, bd->ShaderModuleFrag, v->Allocator); bd->ShaderModuleFrag = VK_NULL_HANDLE; }
@@ -1085,7 +1099,7 @@ bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const ch
return true; 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!"); IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
@@ -1121,11 +1135,9 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend
IM_ASSERT(info->MinImageCount >= 2); IM_ASSERT(info->MinImageCount >= 2);
IM_ASSERT(info->ImageCount >= info->MinImageCount); IM_ASSERT(info->ImageCount >= info->MinImageCount);
if (info->UseDynamicRendering == false) if (info->UseDynamicRendering == false)
IM_ASSERT(render_pass != VK_NULL_HANDLE); IM_ASSERT(info->RenderPass != VK_NULL_HANDLE);
bd->VulkanInitInfo = *info; bd->VulkanInitInfo = *info;
bd->RenderPass = render_pass;
bd->Subpass = info->Subpass;
ImGui_ImplVulkan_CreateDeviceObjects(); ImGui_ImplVulkan_CreateDeviceObjects();
@@ -1231,6 +1243,26 @@ void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set)
vkFreeDescriptorSets(v->Device, v->DescriptorPool, 1, &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 // Internal / Miscellaneous Vulkan Helpers
// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own app.) // (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own app.)
@@ -1318,19 +1350,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) 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); IM_ASSERT(physical_device != VK_NULL_HANDLE && device != VK_NULL_HANDLE);
(void)physical_device; IM_UNUSED(physical_device);
(void)allocator;
// Create Command Buffers // Create Command Buffers
VkResult err; VkResult err;
for (uint32_t i = 0; i < wd->ImageCount; i++) for (uint32_t i = 0; i < wd->ImageCount; i++)
{ {
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i]; ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i];
ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[i];
{ {
VkCommandPoolCreateInfo info = {}; VkCommandPoolCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_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; info.queueFamilyIndex = queue_family;
err = vkCreateCommandPool(device, &info, allocator, &fd->CommandPool); err = vkCreateCommandPool(device, &info, allocator, &fd->CommandPool);
check_vk_result(err); check_vk_result(err);
@@ -1351,6 +1381,11 @@ void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_devi
err = vkCreateFence(device, &info, allocator, &fd->Fence); err = vkCreateFence(device, &info, allocator, &fd->Fence);
check_vk_result(err); check_vk_result(err);
} }
}
for (uint32_t i = 0; i < wd->SemaphoreCount; i++)
{
ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[i];
{ {
VkSemaphoreCreateInfo info = {}; VkSemaphoreCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
@@ -1386,10 +1421,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. // We don't use ImGui_ImplVulkanH_DestroyWindow() because we want to preserve the old swapchain to create the new one.
// Destroy old Framebuffer // Destroy old Framebuffer
for (uint32_t i = 0; i < wd->ImageCount; i++) for (uint32_t i = 0; i < wd->ImageCount; i++)
{
ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator); 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); ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator);
}
IM_FREE(wd->Frames); IM_FREE(wd->Frames);
IM_FREE(wd->FrameSemaphores); IM_FREE(wd->FrameSemaphores);
wd->Frames = nullptr; wd->Frames = nullptr;
@@ -1448,11 +1482,12 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers); err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers);
check_vk_result(err); 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->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->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++) for (uint32_t i = 0; i < wd->ImageCount; i++)
wd->Frames[i].Backbuffer = backbuffers[i]; wd->Frames[i].Backbuffer = backbuffers[i];
} }
@@ -1498,7 +1533,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, // 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: // 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 // Create The Image Views
@@ -1560,10 +1595,9 @@ void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui
//vkQueueWaitIdle(bd->Queue); //vkQueueWaitIdle(bd->Queue);
for (uint32_t i = 0; i < wd->ImageCount; i++) for (uint32_t i = 0; i < wd->ImageCount; i++)
{
ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator); 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); ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator);
}
IM_FREE(wd->Frames); IM_FREE(wd->Frames);
IM_FREE(wd->FrameSemaphores); IM_FREE(wd->FrameSemaphores);
wd->Frames = nullptr; wd->Frames = nullptr;
@@ -1596,32 +1630,12 @@ void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH
fsd->ImageAcquiredSemaphore = fsd->RenderCompleteSemaphore = VK_NULL_HANDLE; 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) void ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(VkDevice device, const VkAllocationCallbacks* allocator)
{ {
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
for (int n = 0; n < platform_io.Viewports.Size; n++) for (int n = 0; n < platform_io.Viewports.Size; n++)
if (ImGui_ImplVulkan_ViewportData* vd = (ImGui_ImplVulkan_ViewportData*)platform_io.Viewports[n]->RendererUserData) 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 +1667,17 @@ static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport)
} }
// Select Surface Format // Select Surface Format
const VkFormat requestSurfaceImageFormat[] = { ImVector<VkFormat> requestSurfaceImageFormats;
#if defined(IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING) #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
v->UseDynamicRendering && v->ColorAttachmentFormat ? v->ColorAttachmentFormat : VK_FORMAT_B8G8R8A8_UNORM, for (uint32_t n = 0; n < v->PipelineRenderingCreateInfo.colorAttachmentCount; n++)
requestSurfaceImageFormats.push_back(v->PipelineRenderingCreateInfo.pColorAttachmentFormats[n]);
#endif #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; 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 // 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) // 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)
@@ -1683,7 +1701,7 @@ static void ImGui_ImplVulkan_DestroyWindow(ImGuiViewport* viewport)
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
if (vd->WindowOwned) if (vd->WindowOwned)
ImGui_ImplVulkanH_DestroyWindow(v->Instance, v->Device, &vd->Window, v->Allocator); 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); IM_DELETE(vd);
} }
viewport->RendererUserData = nullptr; viewport->RendererUserData = nullptr;
@@ -1857,8 +1875,8 @@ static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport, void*)
else else
check_vk_result(err); check_vk_result(err);
wd->FrameIndex = (wd->FrameIndex + 1) % wd->ImageCount; // This is for the next vkWaitForFences() 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->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores
} }
void ImGui_ImplVulkan_InitPlatformInterface() void ImGui_ImplVulkan_InitPlatformInterface()

View File

@@ -47,9 +47,20 @@
#if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES) && !defined(VK_NO_PROTOTYPES) #if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES) && !defined(VK_NO_PROTOTYPES)
#define VK_NO_PROTOTYPES #define VK_NO_PROTOTYPES
#endif #endif
#if defined(VK_USE_PLATFORM_WIN32_KHR) && !defined(NOMINMAX)
#define NOMINMAX
#include <vulkan/vulkan.h> #include <vulkan/vulkan.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() // 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!] // [Please zero-clear before use!]
struct ImGui_ImplVulkan_InitInfo struct ImGui_ImplVulkan_InitInfo
{ {
@@ -58,24 +69,31 @@ struct ImGui_ImplVulkan_InitInfo
VkDevice Device; VkDevice Device;
uint32_t QueueFamily; uint32_t QueueFamily;
VkQueue Queue; 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; VkPipelineCache PipelineCache;
VkDescriptorPool DescriptorPool;
uint32_t Subpass; 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) // (Optional) Dynamic Rendering
bool UseDynamicRendering; // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3. // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3.
VkFormat ColorAttachmentFormat; // Required for dynamic rendering bool UseDynamicRendering;
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo;
#endif
// Allocation, Debugging // (Optional) Allocation, Debugging
const VkAllocationCallbacks* Allocator; const VkAllocationCallbacks* Allocator;
void (*CheckVkResultFn)(VkResult err); 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 // 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_Shutdown();
IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame(); 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); IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE);
@@ -155,6 +173,7 @@ struct ImGui_ImplVulkanH_Window
VkClearValue ClearValue; VkClearValue ClearValue;
uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount) 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 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) 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_Frame* Frames;
ImGui_ImplVulkanH_FrameSemaphores* FrameSemaphores; ImGui_ImplVulkanH_FrameSemaphores* FrameSemaphores;

View File

@@ -18,6 +18,10 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (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-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: 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). // 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 struct ImGui_ImplWGPU_Data
{ {
WGPUDevice wgpuDevice = nullptr; ImGui_ImplWGPU_InitInfo initInfo;
WGPUQueue defaultQueue = nullptr; WGPUDevice wgpuDevice = nullptr;
WGPUTextureFormat renderTargetFormat = WGPUTextureFormat_Undefined; WGPUQueue defaultQueue = nullptr;
WGPUTextureFormat depthStencilFormat = WGPUTextureFormat_Undefined; WGPUTextureFormat renderTargetFormat = WGPUTextureFormat_Undefined;
WGPURenderPipeline pipelineState = nullptr; WGPUTextureFormat depthStencilFormat = WGPUTextureFormat_Undefined;
WGPURenderPipeline pipelineState = nullptr;
RenderResources renderResources; RenderResources renderResources;
FrameResources* pFrameResources = nullptr; FrameResources* pFrameResources = nullptr;
unsigned int numFramesInFlight = 0; unsigned int numFramesInFlight = 0;
unsigned int frameIndex = UINT_MAX; unsigned int frameIndex = UINT_MAX;
}; };
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts // 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); wgpuBufferRelease(res);
res = nullptr; res = nullptr;
} }
static void SafeRelease(WGPUPipelineLayout& res)
{
if (res)
wgpuPipelineLayoutRelease(res);
res = nullptr;
}
static void SafeRelease(WGPURenderPipeline& res) static void SafeRelease(WGPURenderPipeline& res)
{ {
if (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) void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder)
{ {
// Avoid rendering when minimized // 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; return;
// FIXME: Assuming that this only gets called once per frame! // 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 // 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_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); 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) if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue; continue;
@@ -559,9 +578,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
graphics_pipeline_desc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined; graphics_pipeline_desc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined;
graphics_pipeline_desc.primitive.frontFace = WGPUFrontFace_CW; graphics_pipeline_desc.primitive.frontFace = WGPUFrontFace_CW;
graphics_pipeline_desc.primitive.cullMode = WGPUCullMode_None; graphics_pipeline_desc.primitive.cullMode = WGPUCullMode_None;
graphics_pipeline_desc.multisample.count = 1; graphics_pipeline_desc.multisample = bd->initInfo.PipelineMultisampleState;
graphics_pipeline_desc.multisample.mask = UINT_MAX;
graphics_pipeline_desc.multisample.alphaToCoverageEnabled = false;
// Bind group layouts // Bind group layouts
WGPUBindGroupLayoutEntry common_bg_layout_entries[2] = {}; WGPUBindGroupLayoutEntry common_bg_layout_entries[2] = {};
@@ -648,7 +665,13 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
depth_stencil_state.depthWriteEnabled = false; depth_stencil_state.depthWriteEnabled = false;
depth_stencil_state.depthCompare = WGPUCompareFunction_Always; depth_stencil_state.depthCompare = WGPUCompareFunction_Always;
depth_stencil_state.stencilFront.compare = 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.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 // Configure disabled depth-stencil state
graphics_pipeline_desc.depthStencil = (bd->depthStencilFormat == WGPUTextureFormat_Undefined) ? nullptr : &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(vertex_shader_desc.module);
SafeRelease(pixel_shader_desc.module); SafeRelease(pixel_shader_desc.module);
SafeRelease(graphics_pipeline_desc.layout);
SafeRelease(bg_layouts[0]); SafeRelease(bg_layouts[0]);
return true; return true;
@@ -699,7 +723,7 @@ void ImGui_ImplWGPU_InvalidateDeviceObjects()
SafeRelease(bd->pFrameResources[i]); 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(); ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
@@ -710,11 +734,12 @@ bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextur
io.BackendRendererName = "imgui_impl_webgpu"; io.BackendRendererName = "imgui_impl_webgpu";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. 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->defaultQueue = wgpuDeviceGetQueue(bd->wgpuDevice);
bd->renderTargetFormat = rt_format; bd->renderTargetFormat = init_info->RenderTargetFormat;
bd->depthStencilFormat = depth_format; bd->depthStencilFormat = init_info->DepthStencilFormat;
bd->numFramesInFlight = num_frames_in_flight; bd->numFramesInFlight = init_info->NumFramesInFlight;
bd->frameIndex = UINT_MAX; bd->frameIndex = UINT_MAX;
bd->renderResources.FontTexture = nullptr; bd->renderResources.FontTexture = nullptr;
@@ -727,8 +752,8 @@ bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextur
bd->renderResources.ImageBindGroupLayout = nullptr; bd->renderResources.ImageBindGroupLayout = nullptr;
// Create buffers with a default size (they will later be grown as needed) // Create buffers with a default size (they will later be grown as needed)
bd->pFrameResources = new FrameResources[num_frames_in_flight]; bd->pFrameResources = new FrameResources[bd->numFramesInFlight];
for (int i = 0; i < num_frames_in_flight; i++) for (int i = 0; i < bd->numFramesInFlight; i++)
{ {
FrameResources* fr = &bd->pFrameResources[i]; FrameResources* fr = &bd->pFrameResources[i];
fr->IndexBuffer = nullptr; fr->IndexBuffer = nullptr;

View File

@@ -22,7 +22,24 @@
#include <webgpu/webgpu.h> #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 = -1u;
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_Shutdown();
IMGUI_IMPL_API void ImGui_ImplWGPU_NewFrame(); IMGUI_IMPL_API void ImGui_ImplWGPU_NewFrame();
IMGUI_IMPL_API void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder); IMGUI_IMPL_API void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder);

View File

@@ -40,7 +40,7 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (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-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-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. // 2023-09-07: Inputs: Added support for keyboard codepage conversion for when application is compiled in MBCS mode and using a non-Unicode window.

View File

@@ -35,11 +35,265 @@ 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. 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! - Please report any issue!
-----------------------------------------------------------------------
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 tesselation issue when rendering rounded progress bars,
where in some situations the rounded section wouldn't follow regular tesselation 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) VERSION 1.90.0 (Released 2023-11-15)
----------------------------------------------------------------------- -----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.90
Breaking changes: Breaking changes:
- BeginChild(): Upgraded 'bool border = false' parameter to 'ImGuiChildFlags flags = 0'. - BeginChild(): Upgraded 'bool border = false' parameter to 'ImGuiChildFlags flags = 0'.
@@ -153,7 +407,7 @@ Other changes:
with ImGuiDragDropFlags_AcceptNoPreviewTooltip and submitting a tooltip manually. with ImGuiDragDropFlags_AcceptNoPreviewTooltip and submitting a tooltip manually.
- Tables: - Tables:
- Added angled headers support. You need to set ImGuiTableColumnFlags_AngledHeader on selected - 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. - Added ImGuiTableFlags_HighlightHoveredColumn flag, currently highlighting column header.
- Fixed an edge-case when no columns are visible + table scrollbar is visible + user - 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 code is always testing return value of TableSetColumnIndex() to coarse clip. With an active

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. - 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** **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. - 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. 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

@@ -426,7 +426,7 @@ Finally, you may call `ImGui::ShowMetricsWindow()` to explore/visualize/understa
### Q: How can I use maths operators with ImVec2? ### 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) ##### [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. 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: 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). 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. - 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! 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. 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: Because of type usage of `u8""` in C++20 is a little more tedious:
```cpp ```cpp
ImGui::Text((const char*)u8"こんにちは"); ImGui::Text((const char*)u8"こんにちは");
``` ```
We suggest using a macro in your codebase: 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.
```cpp
#define U8(_S) (const char*)u8##_S
ImGui::Text(U8("こんにちは"));
```
##### [Return to Index](#index) ##### [Return to Index](#index)
--------------------------------------- ---------------------------------------
@@ -486,7 +482,7 @@ Some fonts files are available in the `misc/fonts/` folder:
#### MONOSPACE FONTS #### MONOSPACE FONTS
Pixel Perfect: 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.) - 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: Regular:

View File

@@ -16,7 +16,7 @@ Businesses: support continued development and maintenance via invoiced sponsorin
| [The Pitch](#the-pitch) - [Usage](#usage) - [How it works](#how-it-works) - [Releases & Changelogs](#releases--changelogs) - [Demo](#demo) - [Integration](#integration) | | [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) | | [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) | | [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 ### The Pitch
@@ -39,7 +39,7 @@ Dear ImGui is particularly suited to integration in game engines (for tooling),
### Usage ### 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. **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). 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: 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)). 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,6 +139,8 @@ Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas.
### Gallery ### Gallery
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/6897)! For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/6897)!
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. 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.
@@ -207,7 +209,7 @@ Sponsoring, maintenance/support contracts and other B2B transactions are hosted
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." 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). <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. 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

@@ -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. - 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_emscripten_wgpu/` directory.
- Requires recent Emscripten as WGPU is still a work-in-progress API. - Requires recent Emscripten as WGPU is still a work-in-progress API.

View File

@@ -11,13 +11,20 @@
#include "imgui_impl_glfw.h" #include "imgui_impl_glfw.h"
#include "imgui_impl_wgpu.h" #include "imgui_impl_wgpu.h"
#include <stdio.h> #include <stdio.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h> #include <emscripten.h>
#include <emscripten/html5.h> #include <emscripten/html5.h>
#include <emscripten/html5_webgpu.h> #include <emscripten/html5_webgpu.h>
#endif
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <webgpu/webgpu.h> #include <webgpu/webgpu.h>
#include <webgpu/webgpu_cpp.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 // Global WebGPU required states
static WGPUDevice wgpu_device = nullptr; static WGPUDevice wgpu_device = nullptr;
static WGPUSurface wgpu_surface = nullptr; static WGPUSurface wgpu_surface = nullptr;
@@ -27,15 +34,32 @@ static int wgpu_swap_chain_width = 0;
static int wgpu_swap_chain_height = 0; static int wgpu_swap_chain_height = 0;
// Forward declarations // Forward declarations
static void MainLoopStep(void* window);
static bool InitWGPU(); static bool InitWGPU();
static void print_glfw_error(int error, const char* description); static void CreateSwapChain(int width, int height);
static void print_wgpu_error(WGPUErrorType error_type, const char* message, void*);
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 // Main code
int main(int, char**) int main(int, char**)
{ {
glfwSetErrorCallback(print_glfw_error); glfwSetErrorCallback(glfw_error_callback);
if (!glfwInit()) if (!glfwInit())
return 1; return 1;
@@ -43,11 +67,8 @@ int main(int, char**)
// This needs to be done explicitly later. // This needs to be done explicitly later.
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr); GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr);
if (!window) if (window == nullptr)
{
glfwTerminate();
return 1; return 1;
}
// Initialize the WebGPU environment // Initialize the WebGPU environment
if (!InitWGPU()) if (!InitWGPU())
@@ -66,17 +87,21 @@ int main(int, char**)
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad 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 // Setup Dear ImGui style
ImGui::StyleColorsDark(); ImGui::StyleColorsDark();
//ImGui::StyleColorsLight(); //ImGui::StyleColorsLight();
// Setup Platform/Renderer backends // Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForOther(window, true); ImGui_ImplGlfw_InitForOther(window, true);
ImGui_ImplWGPU_Init(wgpu_device, 3, wgpu_preferred_fmt, WGPUTextureFormat_Undefined); #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 // 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. // - 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.
@@ -98,10 +123,117 @@ int main(int, char**)
//IM_ASSERT(font != nullptr); //IM_ASSERT(font != nullptr);
#endif #endif
// This function will directly return and exit the main function. // Our state
// Make sure that no required objects get cleaned up. bool show_demo_window = true;
// This way we can use the browsers 'requestAnimationFrame' to control the rendering. bool show_another_window = false;
emscripten_set_main_loop_arg(MainLoopStep, window, 0, 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();
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);
}
#ifdef __EMSCRIPTEN__
EMSCRIPTEN_MAINLOOP_END;
#endif
// Cleanup
ImGui_ImplWGPU_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwDestroyWindow(window);
glfwTerminate();
return 0; return 0;
} }
@@ -112,7 +244,7 @@ static bool InitWGPU()
if (!wgpu_device) if (!wgpu_device)
return false; return false;
wgpuDeviceSetUncapturedErrorCallback(wgpu_device, print_wgpu_error, nullptr); wgpuDeviceSetUncapturedErrorCallback(wgpu_device, wgpu_error_callback, nullptr);
// Use C++ wrapper due to misbehavior in Emscripten. // Use C++ wrapper due to misbehavior in Emscripten.
// Some offset computation for wgpuInstanceCreateSurface in JavaScript // Some offset computation for wgpuInstanceCreateSurface in JavaScript
@@ -127,127 +259,22 @@ static bool InitWGPU()
wgpu::Surface surface = instance.CreateSurface(&surface_desc); wgpu::Surface surface = instance.CreateSurface(&surface_desc);
wgpu::Adapter adapter = {}; wgpu::Adapter adapter = {};
wgpu_preferred_fmt = (WGPUTextureFormat)surface.GetPreferredFormat(adapter); wgpu_preferred_fmt = (WGPUTextureFormat)surface.GetPreferredFormat(adapter);
wgpu_surface = surface.Release(); wgpu_surface = surface.MoveToCHandle();
return true; return true;
} }
static void MainLoopStep(void* window) static void CreateSwapChain(int width, int height)
{ {
ImGuiIO& io = ImGui::GetIO(); if (wgpu_swap_chain)
wgpuSwapChainRelease(wgpu_swap_chain);
glfwPollEvents(); wgpu_swap_chain_width = width;
wgpu_swap_chain_height = height;
int width, height; WGPUSwapChainDescriptor swap_chain_desc = {};
glfwGetFramebufferSize((GLFWwindow*)window, &width, &height); swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment;
swap_chain_desc.format = wgpu_preferred_fmt;
// React to changes in screen size swap_chain_desc.width = width;
if (width != wgpu_swap_chain_width && height != wgpu_swap_chain_height) swap_chain_desc.height = height;
{ swap_chain_desc.presentMode = WGPUPresentMode_Fifo;
ImGui_ImplWGPU_InvalidateDeviceObjects(); wgpu_swap_chain = wgpuDeviceCreateSwapChain(wgpu_device, wgpu_surface, &swap_chain_desc);
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)))) OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
LIBS = -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -framework CoreVideo -framework QuartzCore 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 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 CXXFLAGS += -Wall -Wformat
CFLAGS = $(CXXFLAGS) CFLAGS = $(CXXFLAGS)

View File

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

View File

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

View File

@@ -31,9 +31,9 @@
#pragma comment(lib, "legacy_stdio_definitions") #pragma comment(lib, "legacy_stdio_definitions")
#endif #endif
//#define IMGUI_UNLIMITED_FRAME_RATE //#define APP_USE_UNLIMITED_FRAME_RATE
#ifdef _DEBUG #ifdef _DEBUG
#define IMGUI_VULKAN_DEBUG_REPORT #define APP_USE_VULKAN_DEBUG_REPORT
#endif #endif
// Data // Data
@@ -64,14 +64,14 @@ static void check_vk_result(VkResult err)
abort(); 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) 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 (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); fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
return VK_FALSE; return VK_FALSE;
} }
#endif // IMGUI_VULKAN_DEBUG_REPORT #endif // APP_USE_VULKAN_DEBUG_REPORT
static bool IsExtensionAvailable(const ImVector<VkExtensionProperties>& properties, const char* extension) static bool IsExtensionAvailable(const ImVector<VkExtensionProperties>& properties, const char* extension)
{ {
@@ -139,7 +139,7 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
#endif #endif
// Enabling validation layers // Enabling validation layers
#ifdef IMGUI_VULKAN_DEBUG_REPORT #ifdef APP_USE_VULKAN_DEBUG_REPORT
const char* layers[] = { "VK_LAYER_KHRONOS_validation" }; const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
create_info.enabledLayerCount = 1; create_info.enabledLayerCount = 1;
create_info.ppEnabledLayerNames = layers; create_info.ppEnabledLayerNames = layers;
@@ -153,7 +153,7 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
check_vk_result(err); check_vk_result(err);
// Setup the debug report callback // Setup the debug report callback
#ifdef IMGUI_VULKAN_DEBUG_REPORT #ifdef APP_USE_VULKAN_DEBUG_REPORT
auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT"); auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
IM_ASSERT(vkCreateDebugReportCallbackEXT != nullptr); IM_ASSERT(vkCreateDebugReportCallbackEXT != nullptr);
VkDebugReportCallbackCreateInfoEXT debug_report_ci = {}; VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
@@ -258,7 +258,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); wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
// Select Present Mode // 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 }; VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR };
#else #else
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR }; VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR };
@@ -275,11 +275,11 @@ static void CleanupVulkan()
{ {
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator); vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
#ifdef IMGUI_VULKAN_DEBUG_REPORT #ifdef APP_USE_VULKAN_DEBUG_REPORT
// Remove the debug report callback // Remove the debug report callback
auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT"); auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator); vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
#endif // IMGUI_VULKAN_DEBUG_REPORT #endif // APP_USE_VULKAN_DEBUG_REPORT
vkDestroyDevice(g_Device, g_Allocator); vkDestroyDevice(g_Device, g_Allocator);
vkDestroyInstance(g_Instance, g_Allocator); vkDestroyInstance(g_Instance, g_Allocator);
@@ -376,7 +376,7 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd)
return; return;
} }
check_vk_result(err); 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 // Main code
@@ -446,13 +446,14 @@ int main(int, char**)
init_info.Queue = g_Queue; init_info.Queue = g_Queue;
init_info.PipelineCache = g_PipelineCache; init_info.PipelineCache = g_PipelineCache;
init_info.DescriptorPool = g_DescriptorPool; init_info.DescriptorPool = g_DescriptorPool;
init_info.RenderPass = wd->RenderPass;
init_info.Subpass = 0; init_info.Subpass = 0;
init_info.MinImageCount = g_MinImageCount; init_info.MinImageCount = g_MinImageCount;
init_info.ImageCount = wd->ImageCount; init_info.ImageCount = wd->ImageCount;
init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
init_info.Allocator = g_Allocator; init_info.Allocator = g_Allocator;
init_info.CheckVkResultFn = check_vk_result; init_info.CheckVkResultFn = check_vk_result;
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass); ImGui_ImplVulkan_Init(&init_info);
// Load Fonts // 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. // - 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

@@ -47,6 +47,12 @@ int main(int, char**)
// Setup window // Setup window
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); 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); 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_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version); SDL_VERSION(&wmInfo.version);
SDL_GetWindowWMInfo(window, &wmInfo); SDL_GetWindowWMInfo(window, &wmInfo);

View File

@@ -41,6 +41,12 @@ int main(int, char**)
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); 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_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); 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_GLContext gl_context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, gl_context); SDL_GL_MakeCurrent(window, gl_context);
SDL_GL_SetSwapInterval(1); // Enable vsync 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_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); 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); 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_GLContext gl_context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, gl_context); SDL_GL_MakeCurrent(window, gl_context);
SDL_GL_SetSwapInterval(1); // Enable vsync SDL_GL_SetSwapInterval(1); // Enable vsync

View File

@@ -38,6 +38,11 @@ int main(int, char**)
// Create window with SDL_Renderer graphics context // Create window with SDL_Renderer graphics context
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); 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); 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); SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
if (renderer == nullptr) if (renderer == nullptr)
{ {

View File

@@ -23,9 +23,9 @@
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
//#include <vulkan/vulkan_beta.h> //#include <vulkan/vulkan_beta.h>
//#define IMGUI_UNLIMITED_FRAME_RATE //#define APP_USE_UNLIMITED_FRAME_RATE
#ifdef _DEBUG #ifdef _DEBUG
#define IMGUI_VULKAN_DEBUG_REPORT #define APP_USE_VULKAN_DEBUG_REPORT
#endif #endif
// Data // Data
@@ -52,14 +52,14 @@ static void check_vk_result(VkResult err)
abort(); 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) 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 (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); fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
return VK_FALSE; return VK_FALSE;
} }
#endif // IMGUI_VULKAN_DEBUG_REPORT #endif // APP_USE_VULKAN_DEBUG_REPORT
static bool IsExtensionAvailable(const ImVector<VkExtensionProperties>& properties, const char* extension) static bool IsExtensionAvailable(const ImVector<VkExtensionProperties>& properties, const char* extension)
{ {
@@ -127,7 +127,7 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
#endif #endif
// Enabling validation layers // Enabling validation layers
#ifdef IMGUI_VULKAN_DEBUG_REPORT #ifdef APP_USE_VULKAN_DEBUG_REPORT
const char* layers[] = { "VK_LAYER_KHRONOS_validation" }; const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
create_info.enabledLayerCount = 1; create_info.enabledLayerCount = 1;
create_info.ppEnabledLayerNames = layers; create_info.ppEnabledLayerNames = layers;
@@ -141,7 +141,7 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
check_vk_result(err); check_vk_result(err);
// Setup the debug report callback // Setup the debug report callback
#ifdef IMGUI_VULKAN_DEBUG_REPORT #ifdef APP_USE_VULKAN_DEBUG_REPORT
auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT"); auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
IM_ASSERT(vkCreateDebugReportCallbackEXT != nullptr); IM_ASSERT(vkCreateDebugReportCallbackEXT != nullptr);
VkDebugReportCallbackCreateInfoEXT debug_report_ci = {}; VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
@@ -246,7 +246,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); wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
// Select Present Mode // 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 }; VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR };
#else #else
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR }; VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR };
@@ -263,11 +263,11 @@ static void CleanupVulkan()
{ {
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator); vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
#ifdef IMGUI_VULKAN_DEBUG_REPORT #ifdef APP_USE_VULKAN_DEBUG_REPORT
// Remove the debug report callback // Remove the debug report callback
auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT"); auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator); vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
#endif // IMGUI_VULKAN_DEBUG_REPORT #endif // APP_USE_VULKAN_DEBUG_REPORT
vkDestroyDevice(g_Device, g_Allocator); vkDestroyDevice(g_Device, g_Allocator);
vkDestroyInstance(g_Instance, g_Allocator); vkDestroyInstance(g_Instance, g_Allocator);
@@ -364,7 +364,7 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd)
return; return;
} }
check_vk_result(err); 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 // Main code
@@ -385,6 +385,11 @@ int main(int, char**)
// Create window with Vulkan graphics context // Create window with Vulkan graphics context
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); 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); 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; ImVector<const char*> extensions;
uint32_t extensions_count = 0; uint32_t extensions_count = 0;
@@ -441,13 +446,14 @@ int main(int, char**)
init_info.Queue = g_Queue; init_info.Queue = g_Queue;
init_info.PipelineCache = g_PipelineCache; init_info.PipelineCache = g_PipelineCache;
init_info.DescriptorPool = g_DescriptorPool; init_info.DescriptorPool = g_DescriptorPool;
init_info.RenderPass = wd->RenderPass;
init_info.Subpass = 0; init_info.Subpass = 0;
init_info.MinImageCount = g_MinImageCount; init_info.MinImageCount = g_MinImageCount;
init_info.ImageCount = wd->ImageCount; init_info.ImageCount = wd->ImageCount;
init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
init_info.Allocator = g_Allocator; init_info.Allocator = g_Allocator;
init_info.CheckVkResultFn = check_vk_result; init_info.CheckVkResultFn = check_vk_result;
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass); ImGui_ImplVulkan_Init(&init_info);
// Load Fonts // 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. // - 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

@@ -64,7 +64,7 @@ int main(int, char**)
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); 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); SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+OpenGL3 example", 1280, 720, window_flags);
if (window == nullptr) if (window == nullptr)
{ {

View File

@@ -35,19 +35,19 @@ int main(int, char**)
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1"); SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
// Create window with SDL_Renderer graphics context // 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); SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+SDL_Renderer example", 1280, 720, window_flags);
if (window == nullptr) if (window == nullptr)
{ {
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1; return -1;
} }
SDL_Renderer* renderer = SDL_CreateRenderer(window, NULL, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); SDL_Renderer* renderer = SDL_CreateRenderer(window, nullptr, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
if (renderer == nullptr) if (renderer == nullptr)
{ {
SDL_Log("Error: SDL_CreateRenderer(): %s\n", SDL_GetError()); SDL_Log("Error: SDL_CreateRenderer(): %s\n", SDL_GetError());
return -1; return -1;
} }
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_ShowWindow(window); SDL_ShowWindow(window);

View File

@@ -74,9 +74,9 @@ int main(int, char**)
{ {
// Create application window // Create application window
//ImGui_ImplWin32_EnableDpiAwareness(); //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); ::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 // Initialize OpenGL
if (!CreateDeviceWGL(hwnd, &g_MainWindow)) if (!CreateDeviceWGL(hwnd, &g_MainWindow))
@@ -134,7 +134,7 @@ int main(int, char**)
// Load Fonts // 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. // - 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. // - 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. // - 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. // - 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. // - 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/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.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()); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL); //IM_ASSERT(font != nullptr);
// Our state // Our state
bool show_demo_window = true; bool show_demo_window = true;
@@ -159,7 +159,7 @@ int main(int, char**)
// Poll and handle messages (inputs, window resize, etc.) // Poll and handle messages (inputs, window resize, etc.)
// See the WndProc() function below for our to dispatch events to the Win32 backend. // See the WndProc() function below for our to dispatch events to the Win32 backend.
MSG msg; MSG msg;
while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE))
{ {
::TranslateMessage(&msg); ::TranslateMessage(&msg);
::DispatchMessage(&msg); ::DispatchMessage(&msg);
@@ -270,7 +270,7 @@ bool CreateDeviceWGL(HWND hWnd, WGL_WindowData* data)
void CleanupDeviceWGL(HWND hWnd, WGL_WindowData* data) void CleanupDeviceWGL(HWND hWnd, WGL_WindowData* data)
{ {
wglMakeCurrent(NULL, NULL); wglMakeCurrent(nullptr, nullptr);
::ReleaseDC(hWnd, data->hDC); ::ReleaseDC(hWnd, data->hDC);
} }

View File

@@ -50,12 +50,14 @@
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available //#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 //---- 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_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) //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
//#define IMGUI_USE_BGRA_PACKED_COLOR //#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 //#define IMGUI_USE_WCHAR32
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version

1417
imgui.cpp

File diff suppressed because it is too large Load Diff

464
imgui.h
View File

@@ -1,4 +1,4 @@
// dear imgui, v1.90.0 // dear imgui, v1.90.4
// (headers) // (headers)
// Help: // Help:
@@ -23,8 +23,8 @@
// Library Version // Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.90.0" #define IMGUI_VERSION "1.90.4"
#define IMGUI_VERSION_NUM 19000 #define IMGUI_VERSION_NUM 19040
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch #define IMGUI_HAS_VIEWPORT // Viewport WIP branch
#define IMGUI_HAS_DOCK // Docking WIP branch #define IMGUI_HAS_DOCK // Docking WIP branch
@@ -36,10 +36,11 @@ Index of this file:
// [SECTION] Forward declarations and basic types // [SECTION] Forward declarations and basic types
// [SECTION] Dear ImGui end-user API functions // [SECTION] Dear ImGui end-user API functions
// [SECTION] Flags & Enumerations // [SECTION] Flags & Enumerations
// [SECTION] Tables API flags and structures (ImGuiTableFlags, ImGuiTableColumnFlags, ImGuiTableRowFlags, ImGuiTableBgTarget, ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs)
// [SECTION] Helpers: Memory allocations macros, ImVector<> // [SECTION] Helpers: Memory allocations macros, ImVector<>
// [SECTION] ImGuiStyle // [SECTION] ImGuiStyle
// [SECTION] ImGuiIO // [SECTION] ImGuiIO
// [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiWindowClass, ImGuiPayload, ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs) // [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiWindowClass, ImGuiPayload)
// [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, Math Operators, ImColor) // [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, Math Operators, ImColor)
// [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawListFlags, ImDrawList, ImDrawData) // [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawListFlags, ImDrawList, ImDrawData)
// [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont) // [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont)
@@ -90,6 +91,8 @@ Index of this file:
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
// Helper Macros - IM_FMTARGS, IM_FMTLIST: Apply printf-style warnings to our formatting functions. // Helper Macros - IM_FMTARGS, IM_FMTLIST: Apply printf-style warnings to our formatting functions.
// (MSVC provides an equivalent mechanism via SAL Annotations but it would require the macros in a different
// location. e.g. #include <sal.h> + void myprintf(_Printf_format_string_ const char* format, ...))
#if !defined(IMGUI_USE_STB_SPRINTF) && defined(__MINGW32__) && !defined(__clang__) #if !defined(IMGUI_USE_STB_SPRINTF) && defined(__MINGW32__) && !defined(__clang__)
#define IM_FMTARGS(FMT) __attribute__((format(gnu_printf, FMT, FMT+1))) #define IM_FMTARGS(FMT) __attribute__((format(gnu_printf, FMT, FMT+1)))
#define IM_FMTLIST(FMT) __attribute__((format(gnu_printf, FMT, 0))) #define IM_FMTLIST(FMT) __attribute__((format(gnu_printf, FMT, 0)))
@@ -122,6 +125,7 @@ Index of this file:
#endif #endif
#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' #pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx'
#pragma clang diagnostic ignored "-Wold-style-cast" #pragma clang diagnostic ignored "-Wold-style-cast"
#pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
#pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter #pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter
#elif defined(__GNUC__) #elif defined(__GNUC__)
@@ -186,7 +190,7 @@ typedef int ImGuiSortDirection; // -> enum ImGuiSortDirection_ // Enum: A
typedef int ImGuiStyleVar; // -> enum ImGuiStyleVar_ // Enum: A variable identifier for styling typedef int ImGuiStyleVar; // -> enum ImGuiStyleVar_ // Enum: A variable identifier for styling
typedef int ImGuiTableBgTarget; // -> enum ImGuiTableBgTarget_ // Enum: A color target for TableSetBgColor() typedef int ImGuiTableBgTarget; // -> enum ImGuiTableBgTarget_ // Enum: A color target for TableSetBgColor()
// Flags (declared as int for compatibility with old C++, to allow using as flags without overhead, and to not pollute the top of this file) // Flags (declared as int to allow using as flags without overhead, and to not pollute the top of this file)
// - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists! // - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists!
// In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // 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. // With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments.
@@ -204,7 +208,7 @@ typedef int ImGuiDragDropFlags; // -> enum ImGuiDragDropFlags_ // Flags: f
typedef int ImGuiFocusedFlags; // -> enum ImGuiFocusedFlags_ // Flags: for IsWindowFocused() typedef int ImGuiFocusedFlags; // -> enum ImGuiFocusedFlags_ // Flags: for IsWindowFocused()
typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: for IsItemHovered(), IsWindowHovered() etc. typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: for IsItemHovered(), IsWindowHovered() etc.
typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText(), InputTextMultiline() typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText(), InputTextMultiline()
typedef int ImGuiKeyChord; // -> ImGuiKey | ImGuiMod_XXX // Flags: for storage only for now: an ImGuiKey optionally OR-ed with one or more ImGuiMod_XXX values. typedef int ImGuiKeyChord; // -> ImGuiKey | ImGuiMod_XXX // Flags: for IsKeyChordPressed(), Shortcut() etc. an ImGuiKey optionally OR-ed with one or more ImGuiMod_XXX values.
typedef int ImGuiPopupFlags; // -> enum ImGuiPopupFlags_ // Flags: for OpenPopup*(), BeginPopupContext*(), IsPopupOpen() typedef int ImGuiPopupFlags; // -> enum ImGuiPopupFlags_ // Flags: for OpenPopup*(), BeginPopupContext*(), IsPopupOpen()
typedef int ImGuiSelectableFlags; // -> enum ImGuiSelectableFlags_ // Flags: for Selectable() typedef int ImGuiSelectableFlags; // -> enum ImGuiSelectableFlags_ // Flags: for Selectable()
typedef int ImGuiSliderFlags; // -> enum ImGuiSliderFlags_ // Flags: for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc. typedef int ImGuiSliderFlags; // -> enum ImGuiSliderFlags_ // Flags: for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc.
@@ -260,6 +264,7 @@ typedef void (*ImGuiMemFreeFunc)(void* ptr, void* user_data);
// ImVec2: 2D vector used to store positions, sizes etc. [Compile-time configurable type] // ImVec2: 2D vector used to store positions, sizes etc. [Compile-time configurable type]
// This is a frequently used type in the API. Consider using IM_VEC2_CLASS_EXTRA to create implicit cast from/to our preferred type. // This is a frequently used type in the API. Consider using IM_VEC2_CLASS_EXTRA to create implicit cast from/to our preferred type.
// Add '#define IMGUI_DEFINE_MATH_OPERATORS' in your imconfig.h file to benefit from courtesy maths operators for those types.
IM_MSVC_RUNTIME_CHECKS_OFF IM_MSVC_RUNTIME_CHECKS_OFF
struct ImVec2 struct ImVec2
{ {
@@ -303,7 +308,7 @@ namespace ImGui
// Main // Main
IMGUI_API ImGuiIO& GetIO(); // access the IO structure (mouse/keyboard/gamepad inputs, time, various configuration options/flags) IMGUI_API ImGuiIO& GetIO(); // access the IO structure (mouse/keyboard/gamepad inputs, time, various configuration options/flags)
IMGUI_API ImGuiStyle& GetStyle(); // access the Style structure (colors, sizes). Always use PushStyleCol(), PushStyleVar() to modify style mid-frame! IMGUI_API ImGuiStyle& GetStyle(); // access the Style structure (colors, sizes). Always use PushStyleColor(), PushStyleVar() to modify style mid-frame!
IMGUI_API void NewFrame(); // start a new Dear ImGui frame, you can submit any command from this point until Render()/EndFrame(). IMGUI_API void NewFrame(); // start a new Dear ImGui frame, you can submit any command from this point until Render()/EndFrame().
IMGUI_API void EndFrame(); // ends the Dear ImGui frame. automatically called by Render(). If you don't need to render data (skipping rendering) you may call EndFrame() without Render()... but you'll have wasted CPU already! If you don't need to render, better to not create any windows and not call NewFrame() at all! IMGUI_API void EndFrame(); // ends the Dear ImGui frame. automatically called by Render(). If you don't need to render data (skipping rendering) you may call EndFrame() without Render()... but you'll have wasted CPU already! If you don't need to render, better to not create any windows and not call NewFrame() at all!
IMGUI_API void Render(); // ends the Dear ImGui frame, finalize the draw data. You can then get call GetDrawData(). IMGUI_API void Render(); // ends the Dear ImGui frame, finalize the draw data. You can then get call GetDrawData().
@@ -345,7 +350,7 @@ namespace ImGui
// - Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window. Child windows can embed their own child. // - Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window. Child windows can embed their own child.
// - Before 1.90 (November 2023), the "ImGuiChildFlags child_flags = 0" parameter was "bool border = false". // - Before 1.90 (November 2023), the "ImGuiChildFlags child_flags = 0" parameter was "bool border = false".
// This API is backward compatible with old code, as we guarantee that ImGuiChildFlags_Border == true. // This API is backward compatible with old code, as we guarantee that ImGuiChildFlags_Border == true.
// Consider updating your old call sites: // Consider updating your old code:
// BeginChild("Name", size, false) -> Begin("Name", size, 0); or Begin("Name", size, ImGuiChildFlags_None); // BeginChild("Name", size, false) -> Begin("Name", size, 0); or Begin("Name", size, ImGuiChildFlags_None);
// BeginChild("Name", size, true) -> Begin("Name", size, ImGuiChildFlags_Border); // BeginChild("Name", size, true) -> Begin("Name", size, ImGuiChildFlags_Border);
// - Manual sizing (each axis can use a different setting e.g. ImVec2(0.0f, 400.0f)): // - Manual sizing (each axis can use a different setting e.g. ImVec2(0.0f, 400.0f)):
@@ -449,7 +454,7 @@ namespace ImGui
IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API
IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul = 1.0f); // retrieve given style color with style alpha applied and optional extra alpha multiplier, packed as a 32-bit value suitable for ImDrawList IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul = 1.0f); // retrieve given style color with style alpha applied and optional extra alpha multiplier, packed as a 32-bit value suitable for ImDrawList
IMGUI_API ImU32 GetColorU32(const ImVec4& col); // retrieve given color with style alpha applied, packed as a 32-bit value suitable for ImDrawList IMGUI_API ImU32 GetColorU32(const ImVec4& col); // retrieve given color with style alpha applied, packed as a 32-bit value suitable for ImDrawList
IMGUI_API ImU32 GetColorU32(ImU32 col); // retrieve given color with style alpha applied, packed as a 32-bit value suitable for ImDrawList IMGUI_API ImU32 GetColorU32(ImU32 col, float alpha_mul = 1.0f); // retrieve given color with style alpha applied, packed as a 32-bit value suitable for ImDrawList
IMGUI_API const ImVec4& GetStyleColorVec4(ImGuiCol idx); // retrieve style color as stored in ImGuiStyle structure. use to feed back into PushStyleColor(), otherwise use GetColorU32() to get style color with style alpha baked in. IMGUI_API const ImVec4& GetStyleColorVec4(ImGuiCol idx); // retrieve style color as stored in ImGuiStyle structure. use to feed back into PushStyleColor(), otherwise use GetColorU32() to get style color with style alpha baked in.
// Layout cursor positioning // Layout cursor positioning
@@ -539,8 +544,9 @@ namespace ImGui
// Widgets: Images // Widgets: Images
// - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples // - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
// - Note that ImageButton() adds style.FramePadding*2.0f to provided size. This is in order to facilitate fitting an image in a button. // - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above.
IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& tint_col = ImVec4(1, 1, 1, 1), const ImVec4& border_col = ImVec4(0, 0, 0, 0)); // - Note that Image() may add +2.0f to provided size if a border is visible, ImageButton() adds style.FramePadding*2.0f to provided size.
IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& tint_col = ImVec4(1, 1, 1, 1), const ImVec4& border_col = ImVec4(0, 0, 0, 0));
IMGUI_API bool ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); IMGUI_API bool ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1));
// Widgets: Combo Box (Dropdown) // Widgets: Combo Box (Dropdown)
@@ -638,9 +644,9 @@ namespace ImGui
IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3); IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3);
IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3);
IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3);
IMGUI_API void TreePush(const char* str_id); // ~ Indent()+PushId(). Already called by TreeNode() when returning true, but you can call TreePush/TreePop yourself if desired. IMGUI_API void TreePush(const char* str_id); // ~ Indent()+PushID(). Already called by TreeNode() when returning true, but you can call TreePush/TreePop yourself if desired.
IMGUI_API void TreePush(const void* ptr_id); // " IMGUI_API void TreePush(const void* ptr_id); // "
IMGUI_API void TreePop(); // ~ Unindent()+PopId() IMGUI_API void TreePop(); // ~ Unindent()+PopID()
IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode
IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop(). IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop().
IMGUI_API bool CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags = 0); // when 'p_visible != NULL': if '*p_visible==true' display an additional small close button on upper right of the header which will set the bool to false when clicked, if '*p_visible==false' don't display the header. IMGUI_API bool CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags = 0); // when 'p_visible != NULL': if '*p_visible==true' display an additional small close button on upper right of the header which will set the bool to false when clicked, if '*p_visible==false' don't display the header.
@@ -715,9 +721,7 @@ namespace ImGui
// - You can bypass the hovering restriction by using ImGuiHoveredFlags_AllowWhenBlockedByPopup when calling IsItemHovered() or IsWindowHovered(). // - You can bypass the hovering restriction by using ImGuiHoveredFlags_AllowWhenBlockedByPopup when calling IsItemHovered() or IsWindowHovered().
// - IMPORTANT: Popup identifiers are relative to the current ID stack, so OpenPopup and BeginPopup generally needs to be at the same level of the stack. // - IMPORTANT: Popup identifiers are relative to the current ID stack, so OpenPopup and BeginPopup generally needs to be at the same level of the stack.
// This is sometimes leading to confusing mistakes. May rework this in the future. // This is sometimes leading to confusing mistakes. May rework this in the future.
// - BeginPopup(): query popup state, if open start appending into the window. Call EndPopup() afterwards if returned true. ImGuiWindowFlags are forwarded to the window.
// Popups: begin/end functions
// - BeginPopup(): query popup state, if open start appending into the window. Call EndPopup() afterwards. ImGuiWindowFlags are forwarded to the window.
// - BeginPopupModal(): block every interaction behind the window, cannot be closed by user, add a dimming background, has a title bar. // - BeginPopupModal(): block every interaction behind the window, cannot be closed by user, add a dimming background, has a title bar.
IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it.
IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // return true if the modal is open, and you can start outputting to it. IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // return true if the modal is open, and you can start outputting to it.
@@ -767,12 +771,10 @@ namespace ImGui
// TableNextColumn() will automatically wrap-around into the next row if needed. // TableNextColumn() will automatically wrap-around into the next row if needed.
// - IMPORTANT: Comparatively to the old Columns() API, we need to call TableNextColumn() for the first column! // - IMPORTANT: Comparatively to the old Columns() API, we need to call TableNextColumn() for the first column!
// - Summary of possible call flow: // - Summary of possible call flow:
// -------------------------------------------------------------------------------------------------------- // - TableNextRow() -> TableSetColumnIndex(0) -> Text("Hello 0") -> TableSetColumnIndex(1) -> Text("Hello 1") // OK
// TableNextRow() -> TableSetColumnIndex(0) -> Text("Hello 0") -> TableSetColumnIndex(1) -> Text("Hello 1") // OK // - TableNextRow() -> TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK
// TableNextRow() -> TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK // - TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK: TableNextColumn() automatically gets to next row!
// TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK: TableNextColumn() automatically gets to next row! // - TableNextRow() -> Text("Hello 0") // Not OK! Missing TableSetColumnIndex() or TableNextColumn()! Text will not appear!
// TableNextRow() -> Text("Hello 0") // Not OK! Missing TableSetColumnIndex() or TableNextColumn()! Text will not appear!
// --------------------------------------------------------------------------------------------------------
// - 5. Call EndTable() // - 5. Call EndTable()
IMGUI_API bool BeginTable(const char* str_id, int column, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0.0f, 0.0f), float inner_width = 0.0f); IMGUI_API bool BeginTable(const char* str_id, int column, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0.0f, 0.0f), float inner_width = 0.0f);
IMGUI_API void EndTable(); // only call EndTable() if BeginTable() returns true! IMGUI_API void EndTable(); // only call EndTable() if BeginTable() returns true!
@@ -993,7 +995,10 @@ namespace ImGui
IMGUI_API const char* SaveIniSettingsToMemory(size_t* out_ini_size = NULL); // return a zero-terminated string with the .ini data which you can save by your own mean. call when io.WantSaveIniSettings is set, then save data by your own mean and clear io.WantSaveIniSettings. IMGUI_API const char* SaveIniSettingsToMemory(size_t* out_ini_size = NULL); // return a zero-terminated string with the .ini data which you can save by your own mean. call when io.WantSaveIniSettings is set, then save data by your own mean and clear io.WantSaveIniSettings.
// Debug Utilities // Debug Utilities
// - Your main debugging friend is the ShowMetricsWindow() function, which is also accessible from Demo->Tools->Metrics Debugger
IMGUI_API void DebugTextEncoding(const char* text); IMGUI_API void DebugTextEncoding(const char* text);
IMGUI_API void DebugFlashStyleColor(ImGuiCol idx);
IMGUI_API void DebugStartItemPicker();
IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // This is called by IMGUI_CHECKVERSION() macro. IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // This is called by IMGUI_CHECKVERSION() macro.
// Memory Allocators // Memory Allocators
@@ -1051,7 +1056,7 @@ enum ImGuiWindowFlags_
ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus,
// [Internal] // [Internal]
ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] On child window: allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows. ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] On child window: share focus scope, allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows.
ImGuiWindowFlags_ChildWindow = 1 << 24, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_ChildWindow = 1 << 24, // Don't use! For internal use by BeginChild()
ImGuiWindowFlags_Tooltip = 1 << 25, // Don't use! For internal use by BeginTooltip() ImGuiWindowFlags_Tooltip = 1 << 25, // Don't use! For internal use by BeginTooltip()
ImGuiWindowFlags_Popup = 1 << 26, // Don't use! For internal use by BeginPopup() ImGuiWindowFlags_Popup = 1 << 26, // Don't use! For internal use by BeginPopup()
@@ -1066,7 +1071,7 @@ enum ImGuiWindowFlags_
}; };
// Flags for ImGui::BeginChild() // Flags for ImGui::BeginChild()
// (Legacy: bot 0 must always correspond to ImGuiChildFlags_Border to be backward compatible with old API using 'bool border = false'. // (Legacy: bit 0 must always correspond to ImGuiChildFlags_Border to be backward compatible with old API using 'bool border = false'.
// About using AutoResizeX/AutoResizeY flags: // About using AutoResizeX/AutoResizeY flags:
// - May be combined with SetNextWindowSizeConstraints() to set a min/max size for each axis (see "Demo->Child->Auto-resize with Constraints"). // - May be combined with SetNextWindowSizeConstraints() to set a min/max size for each axis (see "Demo->Child->Auto-resize with Constraints").
// - Size measurement for a given axis is only performed when the child window is within visible boundaries, or is just appearing. // - Size measurement for a given axis is only performed when the child window is within visible boundaries, or is just appearing.
@@ -1077,7 +1082,7 @@ enum ImGuiWindowFlags_
enum ImGuiChildFlags_ enum ImGuiChildFlags_
{ {
ImGuiChildFlags_None = 0, ImGuiChildFlags_None = 0,
ImGuiChildFlags_Border = 1 << 0, // Show an outer border and enable WindowPadding. (Important: this is always == 1 == true for legacy reason) ImGuiChildFlags_Border = 1 << 0, // Show an outer border and enable WindowPadding. (IMPORTANT: this is always == 1 == true for legacy reason)
ImGuiChildFlags_AlwaysUseWindowPadding = 1 << 1, // Pad with style.WindowPadding even if no border are drawn (no padding by default for non-bordered child windows because it makes more sense) ImGuiChildFlags_AlwaysUseWindowPadding = 1 << 1, // Pad with style.WindowPadding even if no border are drawn (no padding by default for non-bordered child windows because it makes more sense)
ImGuiChildFlags_ResizeX = 1 << 2, // Allow resize from right border (layout direction). Enable .ini saving (unless ImGuiWindowFlags_NoSavedSettings passed to window flags) ImGuiChildFlags_ResizeX = 1 << 2, // Allow resize from right border (layout direction). Enable .ini saving (unless ImGuiWindowFlags_NoSavedSettings passed to window flags)
ImGuiChildFlags_ResizeY = 1 << 3, // Allow resize from bottom border (layout direction). " ImGuiChildFlags_ResizeY = 1 << 3, // Allow resize from bottom border (layout direction). "
@@ -1137,7 +1142,7 @@ enum ImGuiTreeNodeFlags_
ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (bypass the indented area). ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (bypass the indented area).
ImGuiTreeNodeFlags_SpanAllColumns = 1 << 13, // Frame will span all columns of its container table (text will still fit in current column) ImGuiTreeNodeFlags_SpanAllColumns = 1 << 13, // Frame will span all columns of its container table (text will still fit in current column)
ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 14, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop) ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 14, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop)
//ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 14, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 15, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible
ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog, ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog,
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
@@ -1146,8 +1151,8 @@ enum ImGuiTreeNodeFlags_
}; };
// Flags for OpenPopup*(), BeginPopupContext*(), IsPopupOpen() functions. // Flags for OpenPopup*(), BeginPopupContext*(), IsPopupOpen() functions.
// - To be backward compatible with older API which took an 'int mouse_button = 1' argument, we need to treat // - To be backward compatible with older API which took an 'int mouse_button = 1' argument instead of 'ImGuiPopupFlags flags',
// small flags values as a mouse button index, so we encode the mouse button in the first few bits of the flags. // we need to treat small flags values as a mouse button index, so we encode the mouse button in the first few bits of the flags.
// It is therefore guaranteed to be legal to pass a mouse button index in ImGuiPopupFlags. // It is therefore guaranteed to be legal to pass a mouse button index in ImGuiPopupFlags.
// - For the same reason, we exceptionally default the ImGuiPopupFlags argument of BeginPopupContextXXX functions to 1 instead of 0. // - For the same reason, we exceptionally default the ImGuiPopupFlags argument of BeginPopupContextXXX functions to 1 instead of 0.
// IMPORTANT: because the default parameter is 1 (==ImGuiPopupFlags_MouseButtonRight), if you rely on the default parameter // IMPORTANT: because the default parameter is 1 (==ImGuiPopupFlags_MouseButtonRight), if you rely on the default parameter
@@ -1161,10 +1166,12 @@ enum ImGuiPopupFlags_
ImGuiPopupFlags_MouseButtonMiddle = 2, // For BeginPopupContext*(): open on Middle Mouse release. Guaranteed to always be == 2 (same as ImGuiMouseButton_Middle) ImGuiPopupFlags_MouseButtonMiddle = 2, // For BeginPopupContext*(): open on Middle Mouse release. Guaranteed to always be == 2 (same as ImGuiMouseButton_Middle)
ImGuiPopupFlags_MouseButtonMask_ = 0x1F, ImGuiPopupFlags_MouseButtonMask_ = 0x1F,
ImGuiPopupFlags_MouseButtonDefault_ = 1, ImGuiPopupFlags_MouseButtonDefault_ = 1,
ImGuiPopupFlags_NoOpenOverExistingPopup = 1 << 5, // For OpenPopup*(), BeginPopupContext*(): don't open if there's already a popup at the same level of the popup stack ImGuiPopupFlags_NoReopen = 1 << 5, // For OpenPopup*(), BeginPopupContext*(): don't reopen same popup if already open (won't reposition, won't reinitialize navigation)
ImGuiPopupFlags_NoOpenOverItems = 1 << 6, // For BeginPopupContextWindow(): don't return true when hovering items, only when hovering empty space //ImGuiPopupFlags_NoReopenAlwaysNavInit = 1 << 6, // For OpenPopup*(), BeginPopupContext*(): focus and initialize navigation even when not reopening.
ImGuiPopupFlags_AnyPopupId = 1 << 7, // For IsPopupOpen(): ignore the ImGuiID parameter and test for any popup. ImGuiPopupFlags_NoOpenOverExistingPopup = 1 << 7, // For OpenPopup*(), BeginPopupContext*(): don't open if there's already a popup at the same level of the popup stack
ImGuiPopupFlags_AnyPopupLevel = 1 << 8, // For IsPopupOpen(): search/test at any level of the popup stack (default test in the current level) ImGuiPopupFlags_NoOpenOverItems = 1 << 8, // For BeginPopupContextWindow(): don't return true when hovering items, only when hovering empty space
ImGuiPopupFlags_AnyPopupId = 1 << 10, // For IsPopupOpen(): ignore the ImGuiID parameter and test for any popup.
ImGuiPopupFlags_AnyPopupLevel = 1 << 11, // For IsPopupOpen(): search/test at any level of the popup stack (default test in the current level)
ImGuiPopupFlags_AnyPopup = ImGuiPopupFlags_AnyPopupId | ImGuiPopupFlags_AnyPopupLevel, ImGuiPopupFlags_AnyPopup = ImGuiPopupFlags_AnyPopupId | ImGuiPopupFlags_AnyPopupLevel,
}; };
@@ -1205,7 +1212,7 @@ enum ImGuiTabBarFlags_
ImGuiTabBarFlags_Reorderable = 1 << 0, // Allow manually dragging tabs to re-order them + New tabs are appended at the end of list ImGuiTabBarFlags_Reorderable = 1 << 0, // Allow manually dragging tabs to re-order them + New tabs are appended at the end of list
ImGuiTabBarFlags_AutoSelectNewTabs = 1 << 1, // Automatically select new tabs when they appear ImGuiTabBarFlags_AutoSelectNewTabs = 1 << 1, // Automatically select new tabs when they appear
ImGuiTabBarFlags_TabListPopupButton = 1 << 2, // Disable buttons to open the tab list popup ImGuiTabBarFlags_TabListPopupButton = 1 << 2, // Disable buttons to open the tab list popup
ImGuiTabBarFlags_NoCloseWithMiddleMouseButton = 1 << 3, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You can still repro this behavior on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false. ImGuiTabBarFlags_NoCloseWithMiddleMouseButton = 1 << 3, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You may handle this behavior manually on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false.
ImGuiTabBarFlags_NoTabListScrollingButtons = 1 << 4, // Disable scrolling buttons (apply when fitting policy is ImGuiTabBarFlags_FittingPolicyScroll) ImGuiTabBarFlags_NoTabListScrollingButtons = 1 << 4, // Disable scrolling buttons (apply when fitting policy is ImGuiTabBarFlags_FittingPolicyScroll)
ImGuiTabBarFlags_NoTooltip = 1 << 5, // Disable tooltips when hovering a tab ImGuiTabBarFlags_NoTooltip = 1 << 5, // Disable tooltips when hovering a tab
ImGuiTabBarFlags_FittingPolicyResizeDown = 1 << 6, // Resize tabs when they don't fit ImGuiTabBarFlags_FittingPolicyResizeDown = 1 << 6, // Resize tabs when they don't fit
@@ -1218,150 +1225,15 @@ enum ImGuiTabBarFlags_
enum ImGuiTabItemFlags_ enum ImGuiTabItemFlags_
{ {
ImGuiTabItemFlags_None = 0, ImGuiTabItemFlags_None = 0,
ImGuiTabItemFlags_UnsavedDocument = 1 << 0, // Display a dot next to the title + tab is selected when clicking the X + closure is not assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar. ImGuiTabItemFlags_UnsavedDocument = 1 << 0, // Display a dot next to the title + set ImGuiTabItemFlags_NoAssumedClosure.
ImGuiTabItemFlags_SetSelected = 1 << 1, // Trigger flag to programmatically make the tab selected when calling BeginTabItem() ImGuiTabItemFlags_SetSelected = 1 << 1, // Trigger flag to programmatically make the tab selected when calling BeginTabItem()
ImGuiTabItemFlags_NoCloseWithMiddleMouseButton = 1 << 2, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You can still repro this behavior on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false. ImGuiTabItemFlags_NoCloseWithMiddleMouseButton = 1 << 2, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You may handle this behavior manually on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false.
ImGuiTabItemFlags_NoPushId = 1 << 3, // Don't call PushID(tab->ID)/PopID() on BeginTabItem()/EndTabItem() ImGuiTabItemFlags_NoPushId = 1 << 3, // Don't call PushID()/PopID() on BeginTabItem()/EndTabItem()
ImGuiTabItemFlags_NoTooltip = 1 << 4, // Disable tooltip for the given tab ImGuiTabItemFlags_NoTooltip = 1 << 4, // Disable tooltip for the given tab
ImGuiTabItemFlags_NoReorder = 1 << 5, // Disable reordering this tab or having another tab cross over this tab ImGuiTabItemFlags_NoReorder = 1 << 5, // Disable reordering this tab or having another tab cross over this tab
ImGuiTabItemFlags_Leading = 1 << 6, // Enforce the tab position to the left of the tab bar (after the tab list popup button) ImGuiTabItemFlags_Leading = 1 << 6, // Enforce the tab position to the left of the tab bar (after the tab list popup button)
ImGuiTabItemFlags_Trailing = 1 << 7, // Enforce the tab position to the right of the tab bar (before the scrolling buttons) ImGuiTabItemFlags_Trailing = 1 << 7, // Enforce the tab position to the right of the tab bar (before the scrolling buttons)
}; ImGuiTabItemFlags_NoAssumedClosure = 1 << 8, // Tab is selected when trying to close + closure is not immediately assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar.
// Flags for ImGui::BeginTable()
// - Important! Sizing policies have complex and subtle side effects, much more so than you would expect.
// Read comments/demos carefully + experiment with live demos to get acquainted with them.
// - The DEFAULT sizing policies are:
// - Default to ImGuiTableFlags_SizingFixedFit if ScrollX is on, or if host window has ImGuiWindowFlags_AlwaysAutoResize.
// - Default to ImGuiTableFlags_SizingStretchSame if ScrollX is off.
// - When ScrollX is off:
// - Table defaults to ImGuiTableFlags_SizingStretchSame -> all Columns defaults to ImGuiTableColumnFlags_WidthStretch with same weight.
// - Columns sizing policy allowed: Stretch (default), Fixed/Auto.
// - Fixed Columns (if any) will generally obtain their requested width (unless the table cannot fit them all).
// - Stretch Columns will share the remaining width according to their respective weight.
// - Mixed Fixed/Stretch columns is possible but has various side-effects on resizing behaviors.
// The typical use of mixing sizing policies is: any number of LEADING Fixed columns, followed by one or two TRAILING Stretch columns.
// (this is because the visible order of columns have subtle but necessary effects on how they react to manual resizing).
// - When ScrollX is on:
// - Table defaults to ImGuiTableFlags_SizingFixedFit -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed
// - Columns sizing policy allowed: Fixed/Auto mostly.
// - Fixed Columns can be enlarged as needed. Table will show a horizontal scrollbar if needed.
// - When using auto-resizing (non-resizable) fixed columns, querying the content width to use item right-alignment e.g. SetNextItemWidth(-FLT_MIN) doesn't make sense, would create a feedback loop.
// - Using Stretch columns OFTEN DOES NOT MAKE SENSE if ScrollX is on, UNLESS you have specified a value for 'inner_width' in BeginTable().
// If you specify a value for 'inner_width' then effectively the scrolling space is known and Stretch or mixed Fixed/Stretch columns become meaningful again.
// - Read on documentation at the top of imgui_tables.cpp for details.
enum ImGuiTableFlags_
{
// Features
ImGuiTableFlags_None = 0,
ImGuiTableFlags_Resizable = 1 << 0, // Enable resizing columns.
ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers)
ImGuiTableFlags_Hideable = 1 << 2, // Enable hiding/disabling columns in context menu.
ImGuiTableFlags_Sortable = 1 << 3, // Enable sorting. Call TableGetSortSpecs() to obtain sort specs. Also see ImGuiTableFlags_SortMulti and ImGuiTableFlags_SortTristate.
ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width and sort settings in the .ini file.
ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will display table context menu. By default it is available in TableHeadersRow().
// Decorations
ImGuiTableFlags_RowBg = 1 << 6, // Set each RowBg color with ImGuiCol_TableRowBg or ImGuiCol_TableRowBgAlt (equivalent of calling TableSetBgColor with ImGuiTableBgFlags_RowBg0 on each row manually)
ImGuiTableFlags_BordersInnerH = 1 << 7, // Draw horizontal borders between rows.
ImGuiTableFlags_BordersOuterH = 1 << 8, // Draw horizontal borders at the top and bottom.
ImGuiTableFlags_BordersInnerV = 1 << 9, // Draw vertical borders between columns.
ImGuiTableFlags_BordersOuterV = 1 << 10, // Draw vertical borders on the left and right sides.
ImGuiTableFlags_BordersH = ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_BordersOuterH, // Draw horizontal borders.
ImGuiTableFlags_BordersV = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersOuterV, // Draw vertical borders.
ImGuiTableFlags_BordersInner = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersInnerH, // Draw inner borders.
ImGuiTableFlags_BordersOuter = ImGuiTableFlags_BordersOuterV | ImGuiTableFlags_BordersOuterH, // Draw outer borders.
ImGuiTableFlags_Borders = ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter, // Draw all borders.
ImGuiTableFlags_NoBordersInBody = 1 << 11, // [ALPHA] Disable vertical borders in columns Body (borders will always appear in Headers). -> May move to style
ImGuiTableFlags_NoBordersInBodyUntilResize = 1 << 12, // [ALPHA] Disable vertical borders in columns Body until hovered for resize (borders will always appear in Headers). -> May move to style
// Sizing Policy (read above for defaults)
ImGuiTableFlags_SizingFixedFit = 1 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching contents width.
ImGuiTableFlags_SizingFixedSame = 2 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching the maximum contents width of all columns. Implicitly enable ImGuiTableFlags_NoKeepColumnsVisible.
ImGuiTableFlags_SizingStretchProp = 3 << 13, // Columns default to _WidthStretch with default weights proportional to each columns contents widths.
ImGuiTableFlags_SizingStretchSame = 4 << 13, // Columns default to _WidthStretch with default weights all equal, unless overridden by TableSetupColumn().
// Sizing Extra Options
ImGuiTableFlags_NoHostExtendX = 1 << 16, // Make outer width auto-fit to columns, overriding outer_size.x value. Only available when ScrollX/ScrollY are disabled and Stretch columns are not used.
ImGuiTableFlags_NoHostExtendY = 1 << 17, // Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit). Only available when ScrollX/ScrollY are disabled. Data below the limit will be clipped and not visible.
ImGuiTableFlags_NoKeepColumnsVisible = 1 << 18, // Disable keeping column always minimally visible when ScrollX is off and table gets too small. Not recommended if columns are resizable.
ImGuiTableFlags_PreciseWidths = 1 << 19, // Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth.
// Clipping
ImGuiTableFlags_NoClip = 1 << 20, // Disable clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow into other columns). Generally incompatible with TableSetupScrollFreeze().
// Padding
ImGuiTableFlags_PadOuterX = 1 << 21, // Default if BordersOuterV is on. Enable outermost padding. Generally desirable if you have headers.
ImGuiTableFlags_NoPadOuterX = 1 << 22, // Default if BordersOuterV is off. Disable outermost padding.
ImGuiTableFlags_NoPadInnerX = 1 << 23, // Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off).
// Scrolling
ImGuiTableFlags_ScrollX = 1 << 24, // Enable horizontal scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. Changes default sizing policy. Because this creates a child window, ScrollY is currently generally recommended when using ScrollX.
ImGuiTableFlags_ScrollY = 1 << 25, // Enable vertical scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size.
// Sorting
ImGuiTableFlags_SortMulti = 1 << 26, // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).
ImGuiTableFlags_SortTristate = 1 << 27, // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).
// Miscellaneous
ImGuiTableFlags_HighlightHoveredColumn = 1 << 28, // Highlight column headers when hovered (may evolve into a fuller highlight)
// [Internal] Combinations and masks
ImGuiTableFlags_SizingMask_ = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_SizingFixedSame | ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_SizingStretchSame,
};
// Flags for ImGui::TableSetupColumn()
enum ImGuiTableColumnFlags_
{
// Input configuration flags
ImGuiTableColumnFlags_None = 0,
ImGuiTableColumnFlags_Disabled = 1 << 0, // Overriding/master disable flag: hide column, won't show in context menu (unlike calling TableSetColumnEnabled() which manipulates the user accessible state)
ImGuiTableColumnFlags_DefaultHide = 1 << 1, // Default as a hidden/disabled column.
ImGuiTableColumnFlags_DefaultSort = 1 << 2, // Default as a sorting column.
ImGuiTableColumnFlags_WidthStretch = 1 << 3, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _SizingStretchSame or _SizingStretchProp).
ImGuiTableColumnFlags_WidthFixed = 1 << 4, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _SizingFixedFit and table is resizable).
ImGuiTableColumnFlags_NoResize = 1 << 5, // Disable manual resizing.
ImGuiTableColumnFlags_NoReorder = 1 << 6, // Disable manual reordering this column, this will also prevent other columns from crossing over this column.
ImGuiTableColumnFlags_NoHide = 1 << 7, // Disable ability to hide/disable this column.
ImGuiTableColumnFlags_NoClip = 1 << 8, // Disable clipping for this column (all NoClip columns will render in a same draw command).
ImGuiTableColumnFlags_NoSort = 1 << 9, // Disable ability to sort on this field (even if ImGuiTableFlags_Sortable is set on the table).
ImGuiTableColumnFlags_NoSortAscending = 1 << 10, // Disable ability to sort in the ascending direction.
ImGuiTableColumnFlags_NoSortDescending = 1 << 11, // Disable ability to sort in the descending direction.
ImGuiTableColumnFlags_NoHeaderLabel = 1 << 12, // TableHeadersRow() will not submit horizontal label for this column. Convenient for some small columns. Name will still appear in context menu or in angled headers.
ImGuiTableColumnFlags_NoHeaderWidth = 1 << 13, // Disable header text width contribution to automatic column width.
ImGuiTableColumnFlags_PreferSortAscending = 1 << 14, // Make the initial sort direction Ascending when first sorting on this column (default).
ImGuiTableColumnFlags_PreferSortDescending = 1 << 15, // Make the initial sort direction Descending when first sorting on this column.
ImGuiTableColumnFlags_IndentEnable = 1 << 16, // Use current Indent value when entering cell (default for column 0).
ImGuiTableColumnFlags_IndentDisable = 1 << 17, // Ignore current Indent value when entering cell (default for columns > 0). Indentation changes _within_ the cell will still be honored.
ImGuiTableColumnFlags_AngledHeader = 1 << 18, // TableHeadersRow() will submit an angled header row for this column. Note this will add an extra row.
// Output status flags, read-only via TableGetColumnFlags()
ImGuiTableColumnFlags_IsEnabled = 1 << 24, // Status: is enabled == not hidden by user/api (referred to as "Hide" in _DefaultHide and _NoHide) flags.
ImGuiTableColumnFlags_IsVisible = 1 << 25, // Status: is visible == is enabled AND not clipped by scrolling.
ImGuiTableColumnFlags_IsSorted = 1 << 26, // Status: is currently part of the sort specs
ImGuiTableColumnFlags_IsHovered = 1 << 27, // Status: is hovered by mouse
// [Internal] Combinations and masks
ImGuiTableColumnFlags_WidthMask_ = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_WidthFixed,
ImGuiTableColumnFlags_IndentMask_ = ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_IndentDisable,
ImGuiTableColumnFlags_StatusMask_ = ImGuiTableColumnFlags_IsEnabled | ImGuiTableColumnFlags_IsVisible | ImGuiTableColumnFlags_IsSorted | ImGuiTableColumnFlags_IsHovered,
ImGuiTableColumnFlags_NoDirectResize_ = 1 << 30, // [Internal] Disable user resizing this column directly (it may however we resized indirectly from its left edge)
};
// Flags for ImGui::TableNextRow()
enum ImGuiTableRowFlags_
{
ImGuiTableRowFlags_None = 0,
ImGuiTableRowFlags_Headers = 1 << 0, // Identify header row (set default background color + width of its contents accounted differently for auto column width)
};
// Enum for ImGui::TableSetBgColor()
// Background colors are rendering in 3 layers:
// - Layer 0: draw with RowBg0 color if set, otherwise draw with ColumnBg0 if set.
// - Layer 1: draw with RowBg1 color if set, otherwise draw with ColumnBg1 if set.
// - Layer 2: draw with CellBg color if set.
// The purpose of the two row/columns layers is to let you decide if a background color change should override or blend with the existing color.
// When using ImGuiTableFlags_RowBg on the table, each row has the RowBg0 color automatically set for odd/even rows.
// If you set the color of RowBg0 target, your color will override the existing RowBg0 color.
// If you set the color of RowBg1 or ColumnBg1 target, your color will blend over the RowBg0 color.
enum ImGuiTableBgTarget_
{
ImGuiTableBgTarget_None = 0,
ImGuiTableBgTarget_RowBg0 = 1, // Set row background color 0 (generally used for background, automatically set when ImGuiTableFlags_RowBg is used)
ImGuiTableBgTarget_RowBg1 = 2, // Set row background color 1 (generally used for selection marking)
ImGuiTableBgTarget_CellBg = 3, // Set cell background color (top-most color)
}; };
// Flags for ImGui::IsWindowFocused() // Flags for ImGui::IsWindowFocused()
@@ -1504,6 +1376,7 @@ enum ImGuiSortDirection_
// Since >= 1.89 we increased typing (went from int to enum), some legacy code may need a cast to ImGuiKey. // Since >= 1.89 we increased typing (went from int to enum), some legacy code may need a cast to ImGuiKey.
// Read details about the 1.87 and 1.89 transition : https://github.com/ocornut/imgui/issues/4921 // Read details about the 1.87 and 1.89 transition : https://github.com/ocornut/imgui/issues/4921
// Note that "Keys" related to physical keys and are not the same concept as input "Characters", the later are submitted via io.AddInputCharacter(). // Note that "Keys" related to physical keys and are not the same concept as input "Characters", the later are submitted via io.AddInputCharacter().
// The keyboard key enum values are named after the keys on a standard US keyboard, and on other keyboard types the keys reported may not match the keycaps.
enum ImGuiKey : int enum ImGuiKey : int
{ {
// Keyboard // Keyboard
@@ -1629,7 +1502,7 @@ enum ImGuiKey : int
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiKey_ModCtrl = ImGuiMod_Ctrl, ImGuiKey_ModShift = ImGuiMod_Shift, ImGuiKey_ModAlt = ImGuiMod_Alt, ImGuiKey_ModSuper = ImGuiMod_Super, // Renamed in 1.89 ImGuiKey_ModCtrl = ImGuiMod_Ctrl, ImGuiKey_ModShift = ImGuiMod_Shift, ImGuiKey_ModAlt = ImGuiMod_Alt, ImGuiKey_ModSuper = ImGuiMod_Super, // Renamed in 1.89
ImGuiKey_KeyPadEnter = ImGuiKey_KeypadEnter, // Renamed in 1.87 //ImGuiKey_KeyPadEnter = ImGuiKey_KeypadEnter, // Renamed in 1.87
#endif #endif
}; };
@@ -1698,15 +1571,15 @@ enum ImGuiCol_
ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input
ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgHovered,
ImGuiCol_FrameBgActive, ImGuiCol_FrameBgActive,
ImGuiCol_TitleBg, ImGuiCol_TitleBg, // Title bar
ImGuiCol_TitleBgActive, ImGuiCol_TitleBgActive, // Title bar when focused
ImGuiCol_TitleBgCollapsed, ImGuiCol_TitleBgCollapsed, // Title bar when collapsed
ImGuiCol_MenuBarBg, ImGuiCol_MenuBarBg,
ImGuiCol_ScrollbarBg, ImGuiCol_ScrollbarBg,
ImGuiCol_ScrollbarGrab, ImGuiCol_ScrollbarGrab,
ImGuiCol_ScrollbarGrabHovered, ImGuiCol_ScrollbarGrabHovered,
ImGuiCol_ScrollbarGrabActive, ImGuiCol_ScrollbarGrabActive,
ImGuiCol_CheckMark, ImGuiCol_CheckMark, // Checkbox tick and RadioButton circle
ImGuiCol_SliderGrab, ImGuiCol_SliderGrab,
ImGuiCol_SliderGrabActive, ImGuiCol_SliderGrabActive,
ImGuiCol_Button, ImGuiCol_Button,
@@ -1901,7 +1774,7 @@ enum ImGuiMouseSource : int
ImGuiMouseSource_COUNT ImGuiMouseSource_COUNT
}; };
// Enumeration for ImGui::SetWindow***(), SetNextWindow***(), SetNextItem***() functions // Enumeration for ImGui::SetNextWindow***(), SetWindow***(), SetNextItem***() functions
// Represent a condition. // Represent a condition.
// Important: Treat as a regular enum! Do NOT combine multiple values using binary operators! All the functions above treat 0 as a shortcut to ImGuiCond_Always. // Important: Treat as a regular enum! Do NOT combine multiple values using binary operators! All the functions above treat 0 as a shortcut to ImGuiCond_Always.
enum ImGuiCond_ enum ImGuiCond_
@@ -1913,6 +1786,170 @@ enum ImGuiCond_
ImGuiCond_Appearing = 1 << 3, // Set the variable if the object/window is appearing after being hidden/inactive (or the first time) ImGuiCond_Appearing = 1 << 3, // Set the variable if the object/window is appearing after being hidden/inactive (or the first time)
}; };
//-----------------------------------------------------------------------------
// [SECTION] Tables API flags and structures (ImGuiTableFlags, ImGuiTableColumnFlags, ImGuiTableRowFlags, ImGuiTableBgTarget, ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs)
//-----------------------------------------------------------------------------
// Flags for ImGui::BeginTable()
// - Important! Sizing policies have complex and subtle side effects, much more so than you would expect.
// Read comments/demos carefully + experiment with live demos to get acquainted with them.
// - The DEFAULT sizing policies are:
// - Default to ImGuiTableFlags_SizingFixedFit if ScrollX is on, or if host window has ImGuiWindowFlags_AlwaysAutoResize.
// - Default to ImGuiTableFlags_SizingStretchSame if ScrollX is off.
// - When ScrollX is off:
// - Table defaults to ImGuiTableFlags_SizingStretchSame -> all Columns defaults to ImGuiTableColumnFlags_WidthStretch with same weight.
// - Columns sizing policy allowed: Stretch (default), Fixed/Auto.
// - Fixed Columns (if any) will generally obtain their requested width (unless the table cannot fit them all).
// - Stretch Columns will share the remaining width according to their respective weight.
// - Mixed Fixed/Stretch columns is possible but has various side-effects on resizing behaviors.
// The typical use of mixing sizing policies is: any number of LEADING Fixed columns, followed by one or two TRAILING Stretch columns.
// (this is because the visible order of columns have subtle but necessary effects on how they react to manual resizing).
// - When ScrollX is on:
// - Table defaults to ImGuiTableFlags_SizingFixedFit -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed
// - Columns sizing policy allowed: Fixed/Auto mostly.
// - Fixed Columns can be enlarged as needed. Table will show a horizontal scrollbar if needed.
// - When using auto-resizing (non-resizable) fixed columns, querying the content width to use item right-alignment e.g. SetNextItemWidth(-FLT_MIN) doesn't make sense, would create a feedback loop.
// - Using Stretch columns OFTEN DOES NOT MAKE SENSE if ScrollX is on, UNLESS you have specified a value for 'inner_width' in BeginTable().
// If you specify a value for 'inner_width' then effectively the scrolling space is known and Stretch or mixed Fixed/Stretch columns become meaningful again.
// - Read on documentation at the top of imgui_tables.cpp for details.
enum ImGuiTableFlags_
{
// Features
ImGuiTableFlags_None = 0,
ImGuiTableFlags_Resizable = 1 << 0, // Enable resizing columns.
ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers)
ImGuiTableFlags_Hideable = 1 << 2, // Enable hiding/disabling columns in context menu.
ImGuiTableFlags_Sortable = 1 << 3, // Enable sorting. Call TableGetSortSpecs() to obtain sort specs. Also see ImGuiTableFlags_SortMulti and ImGuiTableFlags_SortTristate.
ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width and sort settings in the .ini file.
ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will display table context menu. By default it is available in TableHeadersRow().
// Decorations
ImGuiTableFlags_RowBg = 1 << 6, // Set each RowBg color with ImGuiCol_TableRowBg or ImGuiCol_TableRowBgAlt (equivalent of calling TableSetBgColor with ImGuiTableBgFlags_RowBg0 on each row manually)
ImGuiTableFlags_BordersInnerH = 1 << 7, // Draw horizontal borders between rows.
ImGuiTableFlags_BordersOuterH = 1 << 8, // Draw horizontal borders at the top and bottom.
ImGuiTableFlags_BordersInnerV = 1 << 9, // Draw vertical borders between columns.
ImGuiTableFlags_BordersOuterV = 1 << 10, // Draw vertical borders on the left and right sides.
ImGuiTableFlags_BordersH = ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_BordersOuterH, // Draw horizontal borders.
ImGuiTableFlags_BordersV = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersOuterV, // Draw vertical borders.
ImGuiTableFlags_BordersInner = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersInnerH, // Draw inner borders.
ImGuiTableFlags_BordersOuter = ImGuiTableFlags_BordersOuterV | ImGuiTableFlags_BordersOuterH, // Draw outer borders.
ImGuiTableFlags_Borders = ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter, // Draw all borders.
ImGuiTableFlags_NoBordersInBody = 1 << 11, // [ALPHA] Disable vertical borders in columns Body (borders will always appear in Headers). -> May move to style
ImGuiTableFlags_NoBordersInBodyUntilResize = 1 << 12, // [ALPHA] Disable vertical borders in columns Body until hovered for resize (borders will always appear in Headers). -> May move to style
// Sizing Policy (read above for defaults)
ImGuiTableFlags_SizingFixedFit = 1 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching contents width.
ImGuiTableFlags_SizingFixedSame = 2 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching the maximum contents width of all columns. Implicitly enable ImGuiTableFlags_NoKeepColumnsVisible.
ImGuiTableFlags_SizingStretchProp = 3 << 13, // Columns default to _WidthStretch with default weights proportional to each columns contents widths.
ImGuiTableFlags_SizingStretchSame = 4 << 13, // Columns default to _WidthStretch with default weights all equal, unless overridden by TableSetupColumn().
// Sizing Extra Options
ImGuiTableFlags_NoHostExtendX = 1 << 16, // Make outer width auto-fit to columns, overriding outer_size.x value. Only available when ScrollX/ScrollY are disabled and Stretch columns are not used.
ImGuiTableFlags_NoHostExtendY = 1 << 17, // Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit). Only available when ScrollX/ScrollY are disabled. Data below the limit will be clipped and not visible.
ImGuiTableFlags_NoKeepColumnsVisible = 1 << 18, // Disable keeping column always minimally visible when ScrollX is off and table gets too small. Not recommended if columns are resizable.
ImGuiTableFlags_PreciseWidths = 1 << 19, // Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth.
// Clipping
ImGuiTableFlags_NoClip = 1 << 20, // Disable clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow into other columns). Generally incompatible with TableSetupScrollFreeze().
// Padding
ImGuiTableFlags_PadOuterX = 1 << 21, // Default if BordersOuterV is on. Enable outermost padding. Generally desirable if you have headers.
ImGuiTableFlags_NoPadOuterX = 1 << 22, // Default if BordersOuterV is off. Disable outermost padding.
ImGuiTableFlags_NoPadInnerX = 1 << 23, // Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off).
// Scrolling
ImGuiTableFlags_ScrollX = 1 << 24, // Enable horizontal scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. Changes default sizing policy. Because this creates a child window, ScrollY is currently generally recommended when using ScrollX.
ImGuiTableFlags_ScrollY = 1 << 25, // Enable vertical scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size.
// Sorting
ImGuiTableFlags_SortMulti = 1 << 26, // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).
ImGuiTableFlags_SortTristate = 1 << 27, // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).
// Miscellaneous
ImGuiTableFlags_HighlightHoveredColumn = 1 << 28, // Highlight column headers when hovered (may evolve into a fuller highlight)
// [Internal] Combinations and masks
ImGuiTableFlags_SizingMask_ = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_SizingFixedSame | ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_SizingStretchSame,
};
// Flags for ImGui::TableSetupColumn()
enum ImGuiTableColumnFlags_
{
// Input configuration flags
ImGuiTableColumnFlags_None = 0,
ImGuiTableColumnFlags_Disabled = 1 << 0, // Overriding/master disable flag: hide column, won't show in context menu (unlike calling TableSetColumnEnabled() which manipulates the user accessible state)
ImGuiTableColumnFlags_DefaultHide = 1 << 1, // Default as a hidden/disabled column.
ImGuiTableColumnFlags_DefaultSort = 1 << 2, // Default as a sorting column.
ImGuiTableColumnFlags_WidthStretch = 1 << 3, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _SizingStretchSame or _SizingStretchProp).
ImGuiTableColumnFlags_WidthFixed = 1 << 4, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _SizingFixedFit and table is resizable).
ImGuiTableColumnFlags_NoResize = 1 << 5, // Disable manual resizing.
ImGuiTableColumnFlags_NoReorder = 1 << 6, // Disable manual reordering this column, this will also prevent other columns from crossing over this column.
ImGuiTableColumnFlags_NoHide = 1 << 7, // Disable ability to hide/disable this column.
ImGuiTableColumnFlags_NoClip = 1 << 8, // Disable clipping for this column (all NoClip columns will render in a same draw command).
ImGuiTableColumnFlags_NoSort = 1 << 9, // Disable ability to sort on this field (even if ImGuiTableFlags_Sortable is set on the table).
ImGuiTableColumnFlags_NoSortAscending = 1 << 10, // Disable ability to sort in the ascending direction.
ImGuiTableColumnFlags_NoSortDescending = 1 << 11, // Disable ability to sort in the descending direction.
ImGuiTableColumnFlags_NoHeaderLabel = 1 << 12, // TableHeadersRow() will not submit horizontal label for this column. Convenient for some small columns. Name will still appear in context menu or in angled headers.
ImGuiTableColumnFlags_NoHeaderWidth = 1 << 13, // Disable header text width contribution to automatic column width.
ImGuiTableColumnFlags_PreferSortAscending = 1 << 14, // Make the initial sort direction Ascending when first sorting on this column (default).
ImGuiTableColumnFlags_PreferSortDescending = 1 << 15, // Make the initial sort direction Descending when first sorting on this column.
ImGuiTableColumnFlags_IndentEnable = 1 << 16, // Use current Indent value when entering cell (default for column 0).
ImGuiTableColumnFlags_IndentDisable = 1 << 17, // Ignore current Indent value when entering cell (default for columns > 0). Indentation changes _within_ the cell will still be honored.
ImGuiTableColumnFlags_AngledHeader = 1 << 18, // TableHeadersRow() will submit an angled header row for this column. Note this will add an extra row.
// Output status flags, read-only via TableGetColumnFlags()
ImGuiTableColumnFlags_IsEnabled = 1 << 24, // Status: is enabled == not hidden by user/api (referred to as "Hide" in _DefaultHide and _NoHide) flags.
ImGuiTableColumnFlags_IsVisible = 1 << 25, // Status: is visible == is enabled AND not clipped by scrolling.
ImGuiTableColumnFlags_IsSorted = 1 << 26, // Status: is currently part of the sort specs
ImGuiTableColumnFlags_IsHovered = 1 << 27, // Status: is hovered by mouse
// [Internal] Combinations and masks
ImGuiTableColumnFlags_WidthMask_ = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_WidthFixed,
ImGuiTableColumnFlags_IndentMask_ = ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_IndentDisable,
ImGuiTableColumnFlags_StatusMask_ = ImGuiTableColumnFlags_IsEnabled | ImGuiTableColumnFlags_IsVisible | ImGuiTableColumnFlags_IsSorted | ImGuiTableColumnFlags_IsHovered,
ImGuiTableColumnFlags_NoDirectResize_ = 1 << 30, // [Internal] Disable user resizing this column directly (it may however we resized indirectly from its left edge)
};
// Flags for ImGui::TableNextRow()
enum ImGuiTableRowFlags_
{
ImGuiTableRowFlags_None = 0,
ImGuiTableRowFlags_Headers = 1 << 0, // Identify header row (set default background color + width of its contents accounted differently for auto column width)
};
// Enum for ImGui::TableSetBgColor()
// Background colors are rendering in 3 layers:
// - Layer 0: draw with RowBg0 color if set, otherwise draw with ColumnBg0 if set.
// - Layer 1: draw with RowBg1 color if set, otherwise draw with ColumnBg1 if set.
// - Layer 2: draw with CellBg color if set.
// The purpose of the two row/columns layers is to let you decide if a background color change should override or blend with the existing color.
// When using ImGuiTableFlags_RowBg on the table, each row has the RowBg0 color automatically set for odd/even rows.
// If you set the color of RowBg0 target, your color will override the existing RowBg0 color.
// If you set the color of RowBg1 or ColumnBg1 target, your color will blend over the RowBg0 color.
enum ImGuiTableBgTarget_
{
ImGuiTableBgTarget_None = 0,
ImGuiTableBgTarget_RowBg0 = 1, // Set row background color 0 (generally used for background, automatically set when ImGuiTableFlags_RowBg is used)
ImGuiTableBgTarget_RowBg1 = 2, // Set row background color 1 (generally used for selection marking)
ImGuiTableBgTarget_CellBg = 3, // Set cell background color (top-most color)
};
// Sorting specifications for a table (often handling sort specs for a single column, occasionally more)
// Obtained by calling TableGetSortSpecs().
// When 'SpecsDirty == true' you can sort your data. It will be true with sorting specs have changed since last call, or the first time.
// Make sure to set 'SpecsDirty = false' after sorting, else you may wastefully sort your data every frame!
struct ImGuiTableSortSpecs
{
const ImGuiTableColumnSortSpecs* Specs; // Pointer to sort spec array.
int SpecsCount; // Sort spec count. Most often 1. May be > 1 when ImGuiTableFlags_SortMulti is enabled. May be == 0 when ImGuiTableFlags_SortTristate is enabled.
bool SpecsDirty; // Set to true when specs have changed since last time! Use this to sort again, then clear the flag.
ImGuiTableSortSpecs() { memset(this, 0, sizeof(*this)); }
};
// Sorting specification for one column of a table (sizeof == 12 bytes)
struct ImGuiTableColumnSortSpecs
{
ImGuiID ColumnUserID; // User id of the column (if specified by a TableSetupColumn() call)
ImS16 ColumnIndex; // Index of the column
ImS16 SortOrder; // Index within parent ImGuiTableSortSpecs (always stored in order starting from 0, tables sorted on a single criteria will always have a 0 here)
ImGuiSortDirection SortDirection : 8; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending
ImGuiTableColumnSortSpecs() { memset(this, 0, sizeof(*this)); }
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Helpers: Memory allocations macros, ImVector<> // [SECTION] Helpers: Memory allocations macros, ImVector<>
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -2152,16 +2189,22 @@ struct ImGuiIO
// Debug options // Debug options
//------------------------------------------------------------------ //------------------------------------------------------------------
// Option to enable various debug tools showing buttons that will call the IM_DEBUG_BREAK() macro.
// - The Item Picker tool will be available regardless of this being enabled, in order to maximize its discoverability.
// - Requires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application.
// e.g. io.ConfigDebugIsDebuggerPresent = ::IsDebuggerPresent() on Win32, or refer to ImOsIsDebuggerPresent() imgui_test_engine/imgui_te_utils.cpp for a Unix compatible version).
bool ConfigDebugIsDebuggerPresent; // = false // Enable various tools calling IM_DEBUG_BREAK().
// Tools to test correct Begin/End and BeginChild/EndChild behaviors. // Tools to test correct Begin/End and BeginChild/EndChild behaviors.
// Presently Begin()/End() and BeginChild()/EndChild() needs to ALWAYS be called in tandem, regardless of return value of BeginXXX() // - Presently Begin()/End() and BeginChild()/EndChild() needs to ALWAYS be called in tandem, regardless of return value of BeginXXX()
// This is inconsistent with other BeginXXX functions and create confusion for many users. // - This is inconsistent with other BeginXXX functions and create confusion for many users.
// We expect to update the API eventually. In the meanwhile we provide tools to facilitate checking user-code behavior. // - We expect to update the API eventually. In the meanwhile we provide tools to facilitate checking user-code behavior.
bool ConfigDebugBeginReturnValueOnce;// = false // First-time calls to Begin()/BeginChild() will return false. NEEDS TO BE SET AT APPLICATION BOOT TIME if you don't want to miss windows. bool ConfigDebugBeginReturnValueOnce;// = false // First-time calls to Begin()/BeginChild() will return false. NEEDS TO BE SET AT APPLICATION BOOT TIME if you don't want to miss windows.
bool ConfigDebugBeginReturnValueLoop;// = false // Some calls to Begin()/BeginChild() will return false. Will cycle through window depths then repeat. Suggested use: add "io.ConfigDebugBeginReturnValue = io.KeyShift" in your main loop then occasionally press SHIFT. Windows should be flickering while running. bool ConfigDebugBeginReturnValueLoop;// = false // Some calls to Begin()/BeginChild() will return false. Will cycle through window depths then repeat. Suggested use: add "io.ConfigDebugBeginReturnValue = io.KeyShift" in your main loop then occasionally press SHIFT. Windows should be flickering while running.
// Option to deactivate io.AddFocusEvent(false) handling. May facilitate interactions with a debugger when focus loss leads to clearing inputs data. // Option to deactivate io.AddFocusEvent(false) handling.
// Backends may have other side-effects on focus loss, so this will reduce side-effects but not necessary remove all of them. // - May facilitate interactions with a debugger when focus loss leads to clearing inputs data.
// Consider using e.g. Win32's IsDebuggerPresent() as an additional filter (or see ImOsIsDebuggerPresent() in imgui_test_engine/imgui_te_utils.cpp for a Unix compatible version). // - Backends may have other side-effects on focus loss, so this will reduce side-effects but not necessary remove all of them.
bool ConfigDebugIgnoreFocusLoss; // = false // Ignore io.AddFocusEvent(false), consequently not calling io.ClearInputKeys() in input processing. bool ConfigDebugIgnoreFocusLoss; // = false // Ignore io.AddFocusEvent(false), consequently not calling io.ClearInputKeys() in input processing.
// Option to audit .ini data // Option to audit .ini data
@@ -2214,7 +2257,7 @@ struct ImGuiIO
IMGUI_API void ClearEventsQueue(); // Clear all incoming events. IMGUI_API void ClearEventsQueue(); // Clear all incoming events.
IMGUI_API void ClearInputKeys(); // Clear current keyboard/mouse/gamepad state + current frame text input buffer. Equivalent to releasing all keys/buttons. IMGUI_API void ClearInputKeys(); // Clear current keyboard/mouse/gamepad state + current frame text input buffer. Equivalent to releasing all keys/buttons.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
IMGUI_API void ClearInputCharacters(); // [Obsolete] Clear the current frame text input buffer. Now included within ClearInputKeys(). IMGUI_API void ClearInputCharacters(); // [Obsoleted in 1.89.8] Clear the current frame text input buffer. Now included within ClearInputKeys().
#endif #endif
//------------------------------------------------------------------ //------------------------------------------------------------------
@@ -2244,11 +2287,7 @@ struct ImGuiIO
int KeyMap[ImGuiKey_COUNT]; // [LEGACY] Input: map of indices into the KeysDown[512] entries array which represent your "native" keyboard state. The first 512 are now unused and should be kept zero. Legacy backend will write into KeyMap[] using ImGuiKey_ indices which are always >512. int KeyMap[ImGuiKey_COUNT]; // [LEGACY] Input: map of indices into the KeysDown[512] entries array which represent your "native" keyboard state. The first 512 are now unused and should be kept zero. Legacy backend will write into KeyMap[] using ImGuiKey_ indices which are always >512.
bool KeysDown[ImGuiKey_COUNT]; // [LEGACY] Input: Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). This used to be [512] sized. It is now ImGuiKey_COUNT to allow legacy io.KeysDown[GetKeyIndex(...)] to work without an overflow. bool KeysDown[ImGuiKey_COUNT]; // [LEGACY] Input: Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). This used to be [512] sized. It is now ImGuiKey_COUNT to allow legacy io.KeysDown[GetKeyIndex(...)] to work without an overflow.
float NavInputs[ImGuiNavInput_COUNT]; // [LEGACY] Since 1.88, NavInputs[] was removed. Backends from 1.60 to 1.86 won't build. Feed gamepad inputs via io.AddKeyEvent() and ImGuiKey_GamepadXXX enums. float NavInputs[ImGuiNavInput_COUNT]; // [LEGACY] Since 1.88, NavInputs[] was removed. Backends from 1.60 to 1.86 won't build. Feed gamepad inputs via io.AddKeyEvent() and ImGuiKey_GamepadXXX enums.
#endif //void* ImeWindowHandle; // [Obsoleted in 1.87] Set ImGuiViewport::PlatformHandleRaw instead. Set this to your HWND to get automatic IME cursor positioning.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
void* ImeWindowHandle; // = NULL // [Obsoleted in 1.87] Set ImGuiViewport::PlatformHandleRaw instead. Set this to your HWND to get automatic IME cursor positioning.
#else
void* _UnusedPadding;
#endif #endif
//------------------------------------------------------------------ //------------------------------------------------------------------
@@ -2302,7 +2341,7 @@ struct ImGuiIO
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Misc data structures // [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiPayload)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Shared state of InputText(), passed as an argument to your callback when a ImGuiInputTextFlags_Callback* flag is used. // Shared state of InputText(), passed as an argument to your callback when a ImGuiInputTextFlags_Callback* flag is used.
@@ -2365,6 +2404,7 @@ struct ImGuiWindowClass
{ {
ImGuiID ClassId; // User data. 0 = Default class (unclassed). Windows of different classes cannot be docked with each others. ImGuiID ClassId; // User data. 0 = Default class (unclassed). Windows of different classes cannot be docked with each others.
ImGuiID ParentViewportId; // Hint for the platform backend. -1: use default. 0: request platform backend to not parent the platform. != 0: request platform backend to create a parent<>child relationship between the platform windows. Not conforming backends are free to e.g. parent every viewport to the main viewport or not. ImGuiID ParentViewportId; // Hint for the platform backend. -1: use default. 0: request platform backend to not parent the platform. != 0: request platform backend to create a parent<>child relationship between the platform windows. Not conforming backends are free to e.g. parent every viewport to the main viewport or not.
ImGuiID FocusRouteParentWindowId; // ID of parent window for shortcut focus route evaluation, e.g. Shortcut() call from Parent Window will succeed when this window is focused.
ImGuiViewportFlags ViewportFlagsOverrideSet; // Viewport flags to set when a window of this class owns a viewport. This allows you to enforce OS decoration or task bar icon, override the defaults on a per-window basis. ImGuiViewportFlags ViewportFlagsOverrideSet; // Viewport flags to set when a window of this class owns a viewport. This allows you to enforce OS decoration or task bar icon, override the defaults on a per-window basis.
ImGuiViewportFlags ViewportFlagsOverrideClear; // Viewport flags to clear when a window of this class owns a viewport. This allows you to enforce OS decoration or task bar icon, override the defaults on a per-window basis. ImGuiViewportFlags ViewportFlagsOverrideClear; // Viewport flags to clear when a window of this class owns a viewport. This allows you to enforce OS decoration or task bar icon, override the defaults on a per-window basis.
ImGuiTabItemFlags TabItemFlagsOverrideSet; // [EXPERIMENTAL] TabItem flags to set when a window of this class gets submitted into a dock node tab bar. May use with ImGuiTabItemFlags_Leading or ImGuiTabItemFlags_Trailing. ImGuiTabItemFlags TabItemFlagsOverrideSet; // [EXPERIMENTAL] TabItem flags to set when a window of this class gets submitted into a dock node tab bar. May use with ImGuiTabItemFlags_Leading or ImGuiTabItemFlags_Trailing.
@@ -2397,30 +2437,6 @@ struct ImGuiPayload
bool IsDelivery() const { return Delivery; } bool IsDelivery() const { return Delivery; }
}; };
// Sorting specification for one column of a table (sizeof == 12 bytes)
struct ImGuiTableColumnSortSpecs
{
ImGuiID ColumnUserID; // User id of the column (if specified by a TableSetupColumn() call)
ImS16 ColumnIndex; // Index of the column
ImS16 SortOrder; // Index within parent ImGuiTableSortSpecs (always stored in order starting from 0, tables sorted on a single criteria will always have a 0 here)
ImGuiSortDirection SortDirection : 8; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending
ImGuiTableColumnSortSpecs() { memset(this, 0, sizeof(*this)); }
};
// Sorting specifications for a table (often handling sort specs for a single column, occasionally more)
// Obtained by calling TableGetSortSpecs().
// When 'SpecsDirty == true' you can sort your data. It will be true with sorting specs have changed since last call, or the first time.
// Make sure to set 'SpecsDirty = false' after sorting, else you may wastefully sort your data every frame!
struct ImGuiTableSortSpecs
{
const ImGuiTableColumnSortSpecs* Specs; // Pointer to sort spec array.
int SpecsCount; // Sort spec count. Most often 1. May be > 1 when ImGuiTableFlags_SortMulti is enabled. May be == 0 when ImGuiTableFlags_SortTristate is enabled.
bool SpecsDirty; // Set to true when specs have changed since last time! Use this to sort again, then clear the flag.
ImGuiTableSortSpecs() { memset(this, 0, sizeof(*this)); }
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, Math Operators, ImColor) // [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, Math Operators, ImColor)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -2609,9 +2625,13 @@ static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x
static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; } static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }
static inline ImVec2& operator*=(ImVec2& lhs, const ImVec2& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; return lhs; } static inline ImVec2& operator*=(ImVec2& lhs, const ImVec2& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; return lhs; }
static inline ImVec2& operator/=(ImVec2& lhs, const ImVec2& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; return lhs; } static inline ImVec2& operator/=(ImVec2& lhs, const ImVec2& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; return lhs; }
static inline bool operator==(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; }
static inline bool operator!=(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y; }
static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); }
static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); }
static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); }
static inline bool operator==(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w; }
static inline bool operator!=(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z || lhs.w != rhs.w; }
IM_MSVC_RUNTIME_CHECKS_RESTORE IM_MSVC_RUNTIME_CHECKS_RESTORE
#endif #endif
@@ -2865,7 +2885,8 @@ struct ImDrawList
IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags = 0); IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags = 0);
// Stateful path API, add points then finish with PathFillConvex() or PathStroke() // Stateful path API, add points then finish with PathFillConvex() or PathStroke()
// - Filled shapes must always use clockwise winding order. The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing. // - Important: filled shapes must always use clockwise winding order! The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing.
// so e.g. 'PathArcTo(center, radius, PI * -0.5f, PI)' is ok, whereas 'PathArcTo(center, radius, PI, PI * -0.5f)' won't have correct anti-aliasing when followed by PathFillConvex().
inline void PathClear() { _Path.Size = 0; } inline void PathClear() { _Path.Size = 0; }
inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); }
inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size - 1], &pos, 8) != 0) _Path.push_back(pos); } inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size - 1], &pos, 8) != 0) _Path.push_back(pos); }
@@ -3436,10 +3457,10 @@ namespace ImGui
// OBSOLETED in 1.88 (from May 2022) // OBSOLETED in 1.88 (from May 2022)
static inline void CaptureKeyboardFromApp(bool want_capture_keyboard = true) { SetNextFrameWantCaptureKeyboard(want_capture_keyboard); } // Renamed as name was misleading + removed default value. static inline void CaptureKeyboardFromApp(bool want_capture_keyboard = true) { SetNextFrameWantCaptureKeyboard(want_capture_keyboard); } // Renamed as name was misleading + removed default value.
static inline void CaptureMouseFromApp(bool want_capture_mouse = true) { SetNextFrameWantCaptureMouse(want_capture_mouse); } // Renamed as name was misleading + removed default value. static inline void CaptureMouseFromApp(bool want_capture_mouse = true) { SetNextFrameWantCaptureMouse(want_capture_mouse); } // Renamed as name was misleading + removed default value.
// OBSOLETED in 1.86 (from November 2021)
IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Calculate coarse clipping for large list of evenly sized items. Prefer using ImGuiListClipper.
// Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE) // Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE)
//-- OBSOLETED in 1.86 (from November 2021)
//IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Code removed, see 1.90 for last version of the code. Calculate range of visible items for large list of evenly sized items. Prefer using ImGuiListClipper.
//-- OBSOLETED in 1.85 (from August 2021) //-- OBSOLETED in 1.85 (from August 2021)
//static inline float GetWindowContentRegionWidth() { return GetWindowContentRegionMax().x - GetWindowContentRegionMin().x; } //static inline float GetWindowContentRegionWidth() { return GetWindowContentRegionMax().x - GetWindowContentRegionMin().x; }
//-- OBSOLETED in 1.81 (from February 2021) //-- OBSOLETED in 1.81 (from February 2021)
@@ -3539,9 +3560,14 @@ enum ImGuiModFlags_ { ImGuiModFlags_None = 0, ImGuiModFlags_Ctrl = ImGuiMod_Ctrl
#pragma warning (pop) #pragma warning (pop)
#endif #endif
// Include imgui_user.h at the end of imgui.h (convenient for user to only explicitly include vanilla imgui.h) // Include imgui_user.h at the end of imgui.h
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
#ifdef IMGUI_INCLUDE_IMGUI_USER_H #ifdef IMGUI_INCLUDE_IMGUI_USER_H
#ifdef IMGUI_USER_H_FILENAME
#include IMGUI_USER_H_FILENAME
#else
#include "imgui_user.h" #include "imgui_user.h"
#endif #endif
#endif
#endif // #ifndef IMGUI_DISABLE #endif // #ifndef IMGUI_DISABLE

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.90.0 // dear imgui, v1.90.4
// (demo code) // (demo code)
// Help: // Help:
@@ -54,7 +54,7 @@
// Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp. // Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp.
// Navigating this file: // Navigating this file:
// - In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // - In Visual Studio: 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. // - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments.
/* /*
@@ -172,7 +172,8 @@ Index of this file:
#define IM_MAX(A, B) (((A) >= (B)) ? (A) : (B)) #define IM_MAX(A, B) (((A) >= (B)) ? (A) : (B))
#define IM_CLAMP(V, MN, MX) ((V) < (MN) ? (MN) : (V) > (MX) ? (MX) : (V)) #define IM_CLAMP(V, MN, MX) ((V) < (MN) ? (MN) : (V) > (MX) ? (MX) : (V))
// Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall // Enforce cdecl calling convention for functions called by the standard library,
// in case compilation settings changed the default to e.g. __vectorcall
#ifndef IMGUI_CDECL #ifndef IMGUI_CDECL
#ifdef _MSC_VER #ifdef _MSC_VER
#define IMGUI_CDECL __cdecl #define IMGUI_CDECL __cdecl
@@ -417,6 +418,12 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::MenuItem("Debug Log", NULL, &show_tool_debug_log, has_debug_tools); ImGui::MenuItem("Debug Log", NULL, &show_tool_debug_log, has_debug_tools);
ImGui::MenuItem("ID Stack Tool", NULL, &show_tool_id_stack_tool, has_debug_tools); ImGui::MenuItem("ID Stack Tool", NULL, &show_tool_id_stack_tool, has_debug_tools);
ImGui::MenuItem("Style Editor", NULL, &show_tool_style_editor); ImGui::MenuItem("Style Editor", NULL, &show_tool_style_editor);
bool is_debugger_present = ImGui::GetIO().ConfigDebugIsDebuggerPresent;
if (ImGui::MenuItem("Item Picker", NULL, false, has_debug_tools && is_debugger_present))
ImGui::DebugStartItemPicker();
if (!is_debugger_present)
ImGui::SetItemTooltip("Requires io.ConfigDebugIsDebuggerPresent=true to be set.\n\nWe otherwise disable the menu option to avoid casual users crashing the application.\n\nYou can however always access the Item Picker in Metrics->Tools.");
ImGui::Separator();
ImGui::MenuItem("About Dear ImGui", NULL, &show_tool_about); ImGui::MenuItem("About Dear ImGui", NULL, &show_tool_about);
ImGui::EndMenu(); ImGui::EndMenu();
} }
@@ -476,6 +483,12 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", &io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange); ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", &io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange);
ImGui::SameLine(); HelpMarker("Instruct backend to not alter mouse cursor shape and visibility."); ImGui::SameLine(); HelpMarker("Instruct backend to not alter mouse cursor shape and visibility.");
ImGui::Checkbox("io.ConfigInputTrickleEventQueue", &io.ConfigInputTrickleEventQueue);
ImGui::SameLine(); HelpMarker("Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.");
ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
ImGui::SameLine(); HelpMarker("Instruct Dear ImGui to render a mouse cursor itself. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
ImGui::SeparatorText("Docking");
ImGui::CheckboxFlags("io.ConfigFlags: DockingEnable", &io.ConfigFlags, ImGuiConfigFlags_DockingEnable); ImGui::CheckboxFlags("io.ConfigFlags: DockingEnable", &io.ConfigFlags, ImGuiConfigFlags_DockingEnable);
ImGui::SameLine(); ImGui::SameLine();
if (io.ConfigDockingWithShift) if (io.ConfigDockingWithShift)
@@ -496,6 +509,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::Unindent(); ImGui::Unindent();
} }
ImGui::SeparatorText("Multi-viewports");
ImGui::CheckboxFlags("io.ConfigFlags: ViewportsEnable", &io.ConfigFlags, ImGuiConfigFlags_ViewportsEnable); ImGui::CheckboxFlags("io.ConfigFlags: ViewportsEnable", &io.ConfigFlags, ImGuiConfigFlags_ViewportsEnable);
ImGui::SameLine(); HelpMarker("[beta] Enable beta multi-viewports support. See ImGuiPlatformIO for details."); ImGui::SameLine(); HelpMarker("[beta] Enable beta multi-viewports support. See ImGuiPlatformIO for details.");
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
@@ -512,11 +526,6 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::Unindent(); ImGui::Unindent();
} }
ImGui::Checkbox("io.ConfigInputTrickleEventQueue", &io.ConfigInputTrickleEventQueue);
ImGui::SameLine(); HelpMarker("Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.");
ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
ImGui::SameLine(); HelpMarker("Instruct Dear ImGui to render a mouse cursor itself. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
ImGui::SeparatorText("Widgets"); ImGui::SeparatorText("Widgets");
ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink); ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting)."); ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting).");
@@ -531,10 +540,12 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::Text("Also see Style->Rendering for rendering options."); ImGui::Text("Also see Style->Rendering for rendering options.");
ImGui::SeparatorText("Debug"); ImGui::SeparatorText("Debug");
ImGui::Checkbox("io.ConfigDebugIsDebuggerPresent", &io.ConfigDebugIsDebuggerPresent);
ImGui::SameLine(); HelpMarker("Enable various tools calling IM_DEBUG_BREAK().\n\nRequires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application.");
ImGui::BeginDisabled(); ImGui::BeginDisabled();
ImGui::Checkbox("io.ConfigDebugBeginReturnValueOnce", &io.ConfigDebugBeginReturnValueOnce); // . ImGui::Checkbox("io.ConfigDebugBeginReturnValueOnce", &io.ConfigDebugBeginReturnValueOnce); // .
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::SameLine(); HelpMarker("First calls to Begin()/BeginChild() will return false.\n\nTHIS OPTION IS DISABLED because it needs to be set at application boot-time to make sense. Showing the disabled option is a way to make this feature easier to discover"); ImGui::SameLine(); HelpMarker("First calls to Begin()/BeginChild() will return false.\n\nTHIS OPTION IS DISABLED because it needs to be set at application boot-time to make sense. Showing the disabled option is a way to make this feature easier to discover.");
ImGui::Checkbox("io.ConfigDebugBeginReturnValueLoop", &io.ConfigDebugBeginReturnValueLoop); ImGui::Checkbox("io.ConfigDebugBeginReturnValueLoop", &io.ConfigDebugBeginReturnValueLoop);
ImGui::SameLine(); HelpMarker("Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths then repeat. Windows should be flickering while running."); ImGui::SameLine(); HelpMarker("Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths then repeat. Windows should be flickering while running.");
ImGui::Checkbox("io.ConfigDebugIgnoreFocusLoss", &io.ConfigDebugIgnoreFocusLoss); ImGui::Checkbox("io.ConfigDebugIgnoreFocusLoss", &io.ConfigDebugIgnoreFocusLoss);
@@ -818,7 +829,8 @@ static void ShowDemoWindowWidgets()
static int item_current = 0; static int item_current = 0;
ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items)); ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
ImGui::SameLine(); HelpMarker( ImGui::SameLine(); HelpMarker(
"Using the simplified one-liner Combo API here.\nRefer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API."); "Using the simplified one-liner Combo API here.\n"
"Refer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API.");
} }
{ {
@@ -829,7 +841,8 @@ static void ShowDemoWindowWidgets()
static int item_current = 1; static int item_current = 1;
ImGui::ListBox("listbox", &item_current, items, IM_ARRAYSIZE(items), 4); ImGui::ListBox("listbox", &item_current, items, IM_ARRAYSIZE(items), 4);
ImGui::SameLine(); HelpMarker( ImGui::SameLine(); HelpMarker(
"Using the simplified one-liner ListBox API here.\nRefer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API."); "Using the simplified one-liner ListBox API here.\n"
"Refer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API.");
} }
ImGui::TreePop(); ImGui::TreePop();
@@ -1147,7 +1160,7 @@ static void ShowDemoWindowWidgets()
"CJK text will only appear if the font was loaded with the appropriate CJK character ranges. " "CJK text will only appear if the font was loaded with the appropriate CJK character ranges. "
"Call io.Fonts->AddFontFromFileTTF() manually to load extra character ranges. " "Call io.Fonts->AddFontFromFileTTF() manually to load extra character ranges. "
"Read docs/FONTS.md for details."); "Read docs/FONTS.md for details.");
ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)"); // Normally we would use u8"blah blah" with the proper characters directly in the string. ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)");
ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)"); ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"; static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
//static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis
@@ -1191,7 +1204,7 @@ static void ShowDemoWindowWidgets()
ImVec2 pos = ImGui::GetCursorScreenPos(); ImVec2 pos = ImGui::GetCursorScreenPos();
ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left
ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right
ImVec4 tint_col = use_text_color_for_tint ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint ImVec4 tint_col = use_text_color_for_tint ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
ImVec4 border_col = ImGui::GetStyleColorVec4(ImGuiCol_Border); ImVec4 border_col = ImGui::GetStyleColorVec4(ImGuiCol_Border);
ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, tint_col, border_col); ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, tint_col, border_col);
if (ImGui::BeginItemTooltip()) if (ImGui::BeginItemTooltip())
@@ -1250,9 +1263,9 @@ static void ShowDemoWindowWidgets()
ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", &flags, ImGuiComboFlags_PopupAlignLeft); ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", &flags, ImGuiComboFlags_PopupAlignLeft);
ImGui::SameLine(); HelpMarker("Only makes a difference if the popup is larger than the combo"); ImGui::SameLine(); HelpMarker("Only makes a difference if the popup is larger than the combo");
if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", &flags, ImGuiComboFlags_NoArrowButton)) if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", &flags, ImGuiComboFlags_NoArrowButton))
flags &= ~ImGuiComboFlags_NoPreview; // Clear the other flag, as we cannot combine both flags &= ~ImGuiComboFlags_NoPreview; // Clear incompatible flags
if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", &flags, ImGuiComboFlags_NoPreview)) if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", &flags, ImGuiComboFlags_NoPreview))
flags &= ~(ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_WidthFitPreview); // Clear the other flag, as we cannot combine both flags &= ~(ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_WidthFitPreview); // Clear incompatible flags
if (ImGui::CheckboxFlags("ImGuiComboFlags_WidthFitPreview", &flags, ImGuiComboFlags_WidthFitPreview)) if (ImGui::CheckboxFlags("ImGuiComboFlags_WidthFitPreview", &flags, ImGuiComboFlags_WidthFitPreview))
flags &= ~ImGuiComboFlags_NoPreview; flags &= ~ImGuiComboFlags_NoPreview;
@@ -1269,7 +1282,10 @@ static void ShowDemoWindowWidgets()
// stored in the object itself, etc.) // stored in the object itself, etc.)
const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
static int item_current_idx = 0; // Here we store our selection data as an index. static int item_current_idx = 0; // Here we store our selection data as an index.
const char* combo_preview_value = items[item_current_idx]; // Pass in the preview value visible before opening the combo (it could be anything)
// Pass in the preview value visible before opening the combo (it could technically be different contents or not pulled from items[])
const char* combo_preview_value = items[item_current_idx];
if (ImGui::BeginCombo("combo 1", combo_preview_value, flags)) if (ImGui::BeginCombo("combo 1", combo_preview_value, flags))
{ {
for (int n = 0; n < IM_ARRAYSIZE(items); n++) for (int n = 0; n < IM_ARRAYSIZE(items); n++)
@@ -1309,8 +1325,10 @@ static void ShowDemoWindowWidgets()
IMGUI_DEMO_MARKER("Widgets/List Boxes"); IMGUI_DEMO_MARKER("Widgets/List Boxes");
if (ImGui::TreeNode("List boxes")) if (ImGui::TreeNode("List boxes"))
{ {
// BeginListBox() is essentially a thin wrapper to using BeginChild()/EndChild() with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label. // BeginListBox() is essentially a thin wrapper to using BeginChild()/EndChild()
// You may be tempted to simply use BeginChild() directly, however note that BeginChild() requires EndChild() to always be called (inconsistent with BeginListBox()/EndListBox()). // using the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label.
// You may be tempted to simply use BeginChild() directly. However note that BeginChild() requires EndChild()
// to always be called (inconsistent with BeginListBox()/EndListBox()).
// Using the generic BeginListBox() API, you have full control over how to display the combo contents. // Using the generic BeginListBox() API, you have full control over how to display the combo contents.
// (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively
@@ -1538,6 +1556,7 @@ static void ShowDemoWindowWidgets()
HelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp because we don't want to include <string> in here)"); HelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp because we don't want to include <string> in here)");
ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly); ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly);
ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", &flags, ImGuiInputTextFlags_AllowTabInput); ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", &flags, ImGuiInputTextFlags_AllowTabInput);
ImGui::SameLine(); HelpMarker("When _AllowTabInput is set, passing through the widget with Tabbing doesn't automatically activate it, in order to also cycling through subsequent widgets.");
ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", &flags, ImGuiInputTextFlags_CtrlEnterForNewLine); ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", &flags, ImGuiInputTextFlags_CtrlEnterForNewLine);
ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags); ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags);
ImGui::TreePop(); ImGui::TreePop();
@@ -1628,16 +1647,21 @@ static void ShowDemoWindowWidgets()
}; };
static char buf1[64]; static char buf1[64];
ImGui::InputText("Completion", buf1, 64, ImGuiInputTextFlags_CallbackCompletion, Funcs::MyCallback); ImGui::InputText("Completion", buf1, 64, ImGuiInputTextFlags_CallbackCompletion, Funcs::MyCallback);
ImGui::SameLine(); HelpMarker("Here we append \"..\" each time Tab is pressed. See 'Examples>Console' for a more meaningful demonstration of using this callback."); ImGui::SameLine(); HelpMarker(
"Here we append \"..\" each time Tab is pressed. "
"See 'Examples>Console' for a more meaningful demonstration of using this callback.");
static char buf2[64]; static char buf2[64];
ImGui::InputText("History", buf2, 64, ImGuiInputTextFlags_CallbackHistory, Funcs::MyCallback); ImGui::InputText("History", buf2, 64, ImGuiInputTextFlags_CallbackHistory, Funcs::MyCallback);
ImGui::SameLine(); HelpMarker("Here we replace and select text each time Up/Down are pressed. See 'Examples>Console' for a more meaningful demonstration of using this callback."); ImGui::SameLine(); HelpMarker(
"Here we replace and select text each time Up/Down are pressed. "
"See 'Examples>Console' for a more meaningful demonstration of using this callback.");
static char buf3[64]; static char buf3[64];
static int edit_count = 0; static int edit_count = 0;
ImGui::InputText("Edit", buf3, 64, ImGuiInputTextFlags_CallbackEdit, Funcs::MyCallback, (void*)&edit_count); ImGui::InputText("Edit", buf3, 64, ImGuiInputTextFlags_CallbackEdit, Funcs::MyCallback, (void*)&edit_count);
ImGui::SameLine(); HelpMarker("Here we toggle the casing of the first character on every edit + count edits."); ImGui::SameLine(); HelpMarker(
"Here we toggle the casing of the first character on every edit + count edits.");
ImGui::SameLine(); ImGui::Text("(%d)", edit_count); ImGui::SameLine(); ImGui::Text("(%d)", edit_count);
ImGui::TreePop(); ImGui::TreePop();
@@ -1812,8 +1836,9 @@ static void ShowDemoWindowWidgets()
ImGui::EndPopup(); ImGui::EndPopup();
} }
// Demo Trailing Tabs: click the "+" button to add a new tab (in your app you may want to use a font icon instead of the "+") // Demo Trailing Tabs: click the "+" button to add a new tab.
// Note that we submit it before the regular tabs, but because of the ImGuiTabItemFlags_Trailing flag it will always appear at the end. // (In your app you may want to use a font icon instead of the "+")
// We submit it before the regular tabs, but thanks to the ImGuiTabItemFlags_Trailing flag it will always appear at the end.
if (show_trailing_button) if (show_trailing_button)
if (ImGui::TabItemButton("+", ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip)) if (ImGui::TabItemButton("+", ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip))
active_tabs.push_back(next_tab_id++); // Add new tab active_tabs.push_back(next_tab_id++); // Add new tab
@@ -2097,7 +2122,8 @@ static void ShowDemoWindowWidgets()
if (ImGui::Button("Default: Float + HDR + Hue Wheel")) if (ImGui::Button("Default: Float + HDR + Hue Wheel"))
ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel); ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel);
// Always both a small version of both types of pickers (to make it more visible in the demo to people who are skimming quickly through it) // Always display a small version of both types of pickers
// (that's in order to make it more visible in the demo to people who are skimming quickly through it)
ImGui::Text("Both types:"); ImGui::Text("Both types:");
float w = (ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ItemSpacing.y) * 0.40f; float w = (ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ItemSpacing.y) * 0.40f;
ImGui::SetNextItemWidth(w); ImGui::SetNextItemWidth(w);
@@ -3454,7 +3480,9 @@ static void ShowDemoWindowLayout()
IMGUI_DEMO_MARKER("Layout/Scrolling/Horizontal contents size demo window"); IMGUI_DEMO_MARKER("Layout/Scrolling/Horizontal contents size demo window");
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 0)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 0));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 0)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 0));
HelpMarker("Test of different widgets react and impact the work rectangle growing when horizontal scrolling is enabled.\n\nUse 'Metrics->Tools->Show windows rectangles' to visualize rectangles."); HelpMarker(
"Test how different widgets react and impact the work rectangle growing when horizontal scrolling is enabled.\n\n"
"Use 'Metrics->Tools->Show windows rectangles' to visualize rectangles.");
ImGui::Checkbox("H-scrollbar", &show_h_scrollbar); ImGui::Checkbox("H-scrollbar", &show_h_scrollbar);
ImGui::Checkbox("Button", &show_button); // Will grow contents size (unless explicitly overwritten) ImGui::Checkbox("Button", &show_button); // Will grow contents size (unless explicitly overwritten)
ImGui::Checkbox("Tree nodes", &show_tree_nodes); // Will grow contents size and display highlight over full width ImGui::Checkbox("Tree nodes", &show_tree_nodes); // Will grow contents size and display highlight over full width
@@ -3610,7 +3638,8 @@ static void ShowDemoWindowLayout()
HelpMarker( HelpMarker(
"Hit-testing is by default performed in item submission order, which generally is perceived as 'back-to-front'.\n\n" "Hit-testing is by default performed in item submission order, which generally is perceived as 'back-to-front'.\n\n"
"By using SetNextItemAllowOverlap() you can notify that an item may be overlapped by another. Doing so alters the hovering logic: items using AllowOverlap mode requires an extra frame to accept hovered state."); "By using SetNextItemAllowOverlap() you can notify that an item may be overlapped by another. "
"Doing so alters the hovering logic: items using AllowOverlap mode requires an extra frame to accept hovered state.");
ImGui::Checkbox("Enable AllowOverlap", &enable_allow_overlap); ImGui::Checkbox("Enable AllowOverlap", &enable_allow_overlap);
ImVec2 button1_pos = ImGui::GetCursorScreenPos(); ImVec2 button1_pos = ImGui::GetCursorScreenPos();
@@ -3997,7 +4026,8 @@ struct MyItem
} }
// qsort() is instable so always return a way to differenciate items. // qsort() is instable so always return a way to differenciate items.
// Your own compare function may want to avoid fallback on implicit sort specs e.g. a Name compare if it wasn't already part of the sort specs. // Your own compare function may want to avoid fallback on implicit sort specs.
// e.g. a Name compare if it wasn't already part of the sort specs.
return (a->ID - b->ID); return (a->ID - b->ID);
} }
}; };
@@ -4180,8 +4210,9 @@ static void ShowDemoWindowTables()
// as TableNextColumn() will automatically wrap around and create new rows as needed. // as TableNextColumn() will automatically wrap around and create new rows as needed.
// This is generally more convenient when your cells all contains the same type of data. // This is generally more convenient when your cells all contains the same type of data.
HelpMarker( HelpMarker(
"Only using TableNextColumn(), which tends to be convenient for tables where every cell contains the same type of contents.\n" "Only using TableNextColumn(), which tends to be convenient for tables where every cell contains "
"This is also more similar to the old NextColumn() function of the Columns API, and provided to facilitate the Columns->Tables API transition."); "the same type of contents.\n This is also more similar to the old NextColumn() function of the "
"Columns API, and provided to facilitate the Columns->Tables API transition.");
if (ImGui::BeginTable("table3", 3)) if (ImGui::BeginTable("table3", 3))
{ {
for (int item = 0; item < 14; item++) for (int item = 0; item < 14; item++)
@@ -4237,8 +4268,8 @@ static void ShowDemoWindowTables()
if (ImGui::BeginTable("table1", 3, flags)) if (ImGui::BeginTable("table1", 3, flags))
{ {
// Display headers so we can inspect their interaction with borders. // Display headers so we can inspect their interaction with borders
// (Headers are not the main purpose of this section of the demo, so we are not elaborating on them too much. See other sections for details) // (Headers are not the main purpose of this section of the demo, so we are not elaborating on them now. See other sections for details)
if (display_headers) if (display_headers)
{ {
ImGui::TableSetupColumn("One"); ImGui::TableSetupColumn("One");
@@ -4277,7 +4308,9 @@ static void ShowDemoWindowTables()
PushStyleCompact(); PushStyleCompact();
ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable); ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV); ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV);
ImGui::SameLine(); HelpMarker("Using the _Resizable flag automatically enables the _BordersInnerV flag as well, this is why the resize borders are still showing when unchecking this."); ImGui::SameLine(); HelpMarker(
"Using the _Resizable flag automatically enables the _BordersInnerV flag as well, "
"this is why the resize borders are still showing when unchecking this.");
PopStyleCompact(); PopStyleCompact();
if (ImGui::BeginTable("table1", 3, flags)) if (ImGui::BeginTable("table1", 3, flags))
@@ -4418,7 +4451,8 @@ static void ShowDemoWindowTables()
ImGui::EndTable(); ImGui::EndTable();
} }
// Use outer_size.x == 0.0f instead of default to make the table as tight as possible (only valid when no scrolling and no stretch column) // Use outer_size.x == 0.0f instead of default to make the table as tight as possible
// (only valid when no scrolling and no stretch column)
if (ImGui::BeginTable("table2", 3, flags | ImGuiTableFlags_SizingFixedFit, ImVec2(0.0f, 0.0f))) if (ImGui::BeginTable("table2", 3, flags | ImGuiTableFlags_SizingFixedFit, ImVec2(0.0f, 0.0f)))
{ {
ImGui::TableSetupColumn("One"); ImGui::TableSetupColumn("One");
@@ -4451,7 +4485,8 @@ static void ShowDemoWindowTables()
"e.g.:\n" "e.g.:\n"
"- BorderOuterV\n" "- BorderOuterV\n"
"- any form of row selection\n" "- any form of row selection\n"
"Because of this, activating BorderOuterV sets the default to PadOuterX. Using PadOuterX or NoPadOuterX you can override the default.\n\n" "Because of this, activating BorderOuterV sets the default to PadOuterX. "
"Using PadOuterX or NoPadOuterX you can override the default.\n\n"
"Actual padding values are using style.CellPadding.\n\n" "Actual padding values are using style.CellPadding.\n\n"
"In this demo we don't show horizontal borders to emphasize how they don't affect default horizontal padding."); "In this demo we don't show horizontal borders to emphasize how they don't affect default horizontal padding.");
@@ -4567,7 +4602,8 @@ static void ShowDemoWindowTables()
EditTableSizingFlags(&sizing_policy_flags[table_n]); EditTableSizingFlags(&sizing_policy_flags[table_n]);
// To make it easier to understand the different sizing policy, // To make it easier to understand the different sizing policy,
// For each policy: we display one table where the columns have equal contents width, and one where the columns have different contents width. // For each policy: we display one table where the columns have equal contents width,
// and one where the columns have different contents width.
if (ImGui::BeginTable("table1", 3, sizing_policy_flags[table_n] | flags1)) if (ImGui::BeginTable("table1", 3, sizing_policy_flags[table_n] | flags1))
{ {
for (int row = 0; row < 3; row++) for (int row = 0; row < 3; row++)
@@ -4596,7 +4632,9 @@ static void ShowDemoWindowTables()
ImGui::Spacing(); ImGui::Spacing();
ImGui::TextUnformatted("Advanced"); ImGui::TextUnformatted("Advanced");
ImGui::SameLine(); ImGui::SameLine();
HelpMarker("This section allows you to interact and see the effect of various sizing policies depending on whether Scroll is enabled and the contents of your columns."); HelpMarker(
"This section allows you to interact and see the effect of various sizing policies "
"depending on whether Scroll is enabled and the contents of your columns.");
enum ContentsType { CT_ShowWidth, CT_ShortText, CT_LongText, CT_Button, CT_FillButton, CT_InputText }; enum ContentsType { CT_ShowWidth, CT_ShortText, CT_LongText, CT_Button, CT_FillButton, CT_InputText };
static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable; static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable;
@@ -4611,7 +4649,9 @@ static void ShowDemoWindowTables()
if (contents_type == CT_FillButton) if (contents_type == CT_FillButton)
{ {
ImGui::SameLine(); ImGui::SameLine();
HelpMarker("Be mindful that using right-alignment (e.g. size.x = -FLT_MIN) creates a feedback loop where contents width can feed into auto-column width can feed into contents width."); HelpMarker(
"Be mindful that using right-alignment (e.g. size.x = -FLT_MIN) creates a feedback loop "
"where contents width can feed into auto-column width can feed into contents width.");
} }
ImGui::DragInt("Columns", &column_count, 0.1f, 1, 64, "%d", ImGuiSliderFlags_AlwaysClamp); ImGui::DragInt("Columns", &column_count, 0.1f, 1, 64, "%d", ImGuiSliderFlags_AlwaysClamp);
ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable); ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
@@ -4657,7 +4697,9 @@ static void ShowDemoWindowTables()
IMGUI_DEMO_MARKER("Tables/Vertical scrolling, with clipping"); IMGUI_DEMO_MARKER("Tables/Vertical scrolling, with clipping");
if (ImGui::TreeNode("Vertical scrolling, with clipping")) if (ImGui::TreeNode("Vertical scrolling, with clipping"))
{ {
HelpMarker("Here we activate ScrollY, which will create a child window container to allow hosting scrollable contents.\n\nWe also demonstrate using ImGuiListClipper to virtualize the submission of many items."); HelpMarker(
"Here we activate ScrollY, which will create a child window container to allow hosting scrollable contents.\n\n"
"We also demonstrate using ImGuiListClipper to virtualize the submission of many items.");
static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable; static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
PushStyleCompact(); PushStyleCompact();
@@ -4703,8 +4745,9 @@ static void ShowDemoWindowTables()
HelpMarker( HelpMarker(
"When ScrollX is enabled, the default sizing policy becomes ImGuiTableFlags_SizingFixedFit, " "When ScrollX is enabled, the default sizing policy becomes ImGuiTableFlags_SizingFixedFit, "
"as automatically stretching columns doesn't make much sense with horizontal scrolling.\n\n" "as automatically stretching columns doesn't make much sense with horizontal scrolling.\n\n"
"Also note that as of the current version, you will almost always want to enable ScrollY along with ScrollX," "Also note that as of the current version, you will almost always want to enable ScrollY along with ScrollX, "
"because the container window won't automatically extend vertically to fix contents (this may be improved in future versions)."); "because the container window won't automatically extend vertically to fix contents "
"(this may be improved in future versions).");
static ImGuiTableFlags flags = ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable; static ImGuiTableFlags flags = ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
static int freeze_cols = 1; static int freeze_cols = 1;
static int freeze_rows = 1; static int freeze_rows = 1;
@@ -4761,7 +4804,8 @@ static void ShowDemoWindowTables()
HelpMarker( HelpMarker(
"Showcase using Stretch columns + ScrollX together: " "Showcase using Stretch columns + ScrollX together: "
"this is rather unusual and only makes sense when specifying an 'inner_width' for the table!\n" "this is rather unusual and only makes sense when specifying an 'inner_width' for the table!\n"
"Without an explicit value, inner_width is == outer_size.x and therefore using Stretch columns + ScrollX together doesn't make sense."); "Without an explicit value, inner_width is == outer_size.x and therefore using Stretch columns "
"along with ScrollX doesn't make sense.");
static ImGuiTableFlags flags2 = ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg | ImGuiTableFlags_ContextMenuInBody; static ImGuiTableFlags flags2 = ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg | ImGuiTableFlags_ContextMenuInBody;
static float inner_width = 1000.0f; static float inner_width = 1000.0f;
PushStyleCompact(); PushStyleCompact();
@@ -4819,8 +4863,9 @@ static void ShowDemoWindowTables()
} }
// Create the real table we care about for the example! // Create the real table we care about for the example!
// We use a scrolling table to be able to showcase the difference between the _IsEnabled and _IsVisible flags above, otherwise in // We use a scrolling table to be able to showcase the difference between the _IsEnabled and _IsVisible flags above,
// a non-scrolling table columns are always visible (unless using ImGuiTableFlags_NoKeepColumnsVisible + resizing the parent window down) // otherwise in a non-scrolling table columns are always visible (unless using ImGuiTableFlags_NoKeepColumnsVisible
// + resizing the parent window down).
const ImGuiTableFlags flags const ImGuiTableFlags flags
= ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY
| ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV
@@ -4842,7 +4887,8 @@ static void ShowDemoWindowTables()
float indent_step = (float)((int)TEXT_BASE_WIDTH / 2); float indent_step = (float)((int)TEXT_BASE_WIDTH / 2);
for (int row = 0; row < 8; row++) for (int row = 0; row < 8; row++)
{ {
ImGui::Indent(indent_step); // Add some indentation to demonstrate usage of per-column IndentEnable/IndentDisable flags. // Add some indentation to demonstrate usage of per-column IndentEnable/IndentDisable flags.
ImGui::Indent(indent_step);
ImGui::TableNextRow(); ImGui::TableNextRow();
for (int column = 0; column < column_count; column++) for (int column = 0; column < column_count; column++)
{ {
@@ -4891,7 +4937,9 @@ static void ShowDemoWindowTables()
ImGui::EndTable(); ImGui::EndTable();
} }
HelpMarker("Using TableSetupColumn() to setup explicit width.\n\nUnless _NoKeepColumnsVisible is set, fixed columns with set width may still be shrunk down if there's not enough space in the host."); HelpMarker(
"Using TableSetupColumn() to setup explicit width.\n\nUnless _NoKeepColumnsVisible is set, "
"fixed columns with set width may still be shrunk down if there's not enough space in the host.");
static ImGuiTableFlags flags2 = ImGuiTableFlags_None; static ImGuiTableFlags flags2 = ImGuiTableFlags_None;
PushStyleCompact(); PushStyleCompact();
@@ -4901,7 +4949,8 @@ static void ShowDemoWindowTables()
PopStyleCompact(); PopStyleCompact();
if (ImGui::BeginTable("table2", 4, flags2)) if (ImGui::BeginTable("table2", 4, flags2))
{ {
// We could also set ImGuiTableFlags_SizingFixedFit on the table and all columns will default to ImGuiTableColumnFlags_WidthFixed. // We could also set ImGuiTableFlags_SizingFixedFit on the table and then all columns
// will default to ImGuiTableColumnFlags_WidthFixed.
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 100.0f); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 100.0f);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 15.0f); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 15.0f);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 30.0f); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 30.0f);
@@ -4973,7 +5022,10 @@ static void ShowDemoWindowTables()
IMGUI_DEMO_MARKER("Tables/Row height"); IMGUI_DEMO_MARKER("Tables/Row height");
if (ImGui::TreeNode("Row height")) if (ImGui::TreeNode("Row height"))
{ {
HelpMarker("You can pass a 'min_row_height' to TableNextRow().\n\nRows are padded with 'style.CellPadding.y' on top and bottom, so effectively the minimum row height will always be >= 'style.CellPadding.y * 2.0f'.\n\nWe cannot honor a _maximum_ row height as that would require a unique clipping rectangle per row."); HelpMarker(
"You can pass a 'min_row_height' to TableNextRow().\n\nRows are padded with 'style.CellPadding.y' on top and bottom, "
"so effectively the minimum row height will always be >= 'style.CellPadding.y * 2.0f'.\n\n"
"We cannot honor a _maximum_ row height as that would require a unique clipping rectangle per row.");
if (ImGui::BeginTable("table_row_height", 1, ImGuiTableFlags_Borders)) if (ImGui::BeginTable("table_row_height", 1, ImGuiTableFlags_Borders))
{ {
for (int row = 0; row < 8; row++) for (int row = 0; row < 8; row++)
@@ -4986,7 +5038,10 @@ static void ShowDemoWindowTables()
ImGui::EndTable(); ImGui::EndTable();
} }
HelpMarker("Showcase using SameLine(0,0) to share Current Line Height between cells.\n\nPlease note that Tables Row Height is not the same thing as Current Line Height, as a table cell may contains multiple lines."); HelpMarker(
"Showcase using SameLine(0,0) to share Current Line Height between cells.\n\n"
"Please note that Tables Row Height is not the same thing as Current Line Height, "
"as a table cell may contains multiple lines.");
if (ImGui::BeginTable("table_share_lineheight", 2, ImGuiTableFlags_Borders)) if (ImGui::BeginTable("table_share_lineheight", 2, ImGuiTableFlags_Borders))
{ {
ImGui::TableNextRow(); ImGui::TableNextRow();
@@ -5236,7 +5291,8 @@ static void ShowDemoWindowTables()
{ {
HelpMarker( HelpMarker(
"Showcase using PushItemWidth() and how it is preserved on a per-column basis.\n\n" "Showcase using PushItemWidth() and how it is preserved on a per-column basis.\n\n"
"Note that on auto-resizing non-resizable fixed columns, querying the content width for e.g. right-alignment doesn't make sense."); "Note that on auto-resizing non-resizable fixed columns, querying the content width for "
"e.g. right-alignment doesn't make sense.");
if (ImGui::BeginTable("table_item_width", 3, ImGuiTableFlags_Borders)) if (ImGui::BeginTable("table_item_width", 3, ImGuiTableFlags_Borders))
{ {
ImGui::TableSetupColumn("small"); ImGui::TableSetupColumn("small");
@@ -5333,23 +5389,26 @@ static void ShowDemoWindowTables()
const int rows_count = 12; const int rows_count = 12;
static ImGuiTableFlags table_flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_Hideable | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_HighlightHoveredColumn; static ImGuiTableFlags table_flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_Hideable | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_HighlightHoveredColumn;
static ImGuiTableColumnFlags column_flags = ImGuiTableColumnFlags_AngledHeader | ImGuiTableColumnFlags_WidthFixed;
static bool bools[columns_count * rows_count] = {}; // Dummy storage selection storage static bool bools[columns_count * rows_count] = {}; // Dummy storage selection storage
static int frozen_cols = 1; static int frozen_cols = 1;
static int frozen_rows = 2; static int frozen_rows = 2;
ImGui::CheckboxFlags("_ScrollX", &table_flags, ImGuiTableFlags_ScrollX); ImGui::CheckboxFlags("_ScrollX", &table_flags, ImGuiTableFlags_ScrollX);
ImGui::CheckboxFlags("_ScrollY", &table_flags, ImGuiTableFlags_ScrollY); ImGui::CheckboxFlags("_ScrollY", &table_flags, ImGuiTableFlags_ScrollY);
ImGui::CheckboxFlags("_Resizable", &table_flags, ImGuiTableFlags_Resizable);
ImGui::CheckboxFlags("_NoBordersInBody", &table_flags, ImGuiTableFlags_NoBordersInBody); ImGui::CheckboxFlags("_NoBordersInBody", &table_flags, ImGuiTableFlags_NoBordersInBody);
ImGui::CheckboxFlags("_HighlightHoveredColumn", &table_flags, ImGuiTableFlags_HighlightHoveredColumn); ImGui::CheckboxFlags("_HighlightHoveredColumn", &table_flags, ImGuiTableFlags_HighlightHoveredColumn);
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
ImGui::SliderInt("Frozen columns", &frozen_cols, 0, 2); ImGui::SliderInt("Frozen columns", &frozen_cols, 0, 2);
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
ImGui::SliderInt("Frozen rows", &frozen_rows, 0, 2); ImGui::SliderInt("Frozen rows", &frozen_rows, 0, 2);
ImGui::CheckboxFlags("Disable header contributing to column width", &column_flags, ImGuiTableColumnFlags_NoHeaderWidth);
if (ImGui::BeginTable("table_angled_headers", columns_count, table_flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 12))) if (ImGui::BeginTable("table_angled_headers", columns_count, table_flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 12)))
{ {
ImGui::TableSetupColumn(column_names[0], ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_NoReorder); ImGui::TableSetupColumn(column_names[0], ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_NoReorder);
for (int n = 1; n < columns_count; n++) for (int n = 1; n < columns_count; n++)
ImGui::TableSetupColumn(column_names[n], ImGuiTableColumnFlags_AngledHeader | ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn(column_names[n], column_flags);
ImGui::TableSetupScrollFreeze(frozen_cols, frozen_rows); ImGui::TableSetupScrollFreeze(frozen_cols, frozen_rows);
ImGui::TableAngledHeadersRow(); // Draw angled headers for all columns with the ImGuiTableColumnFlags_AngledHeader flag. ImGui::TableAngledHeadersRow(); // Draw angled headers for all columns with the ImGuiTableColumnFlags_AngledHeader flag.
@@ -5375,13 +5434,16 @@ static void ShowDemoWindowTables()
ImGui::TreePop(); ImGui::TreePop();
} }
// Demonstrate creating custom context menus inside columns, while playing it nice with context menus provided by TableHeadersRow()/TableHeader() // Demonstrate creating custom context menus inside columns,
// while playing it nice with context menus provided by TableHeadersRow()/TableHeader()
if (open_action != -1) if (open_action != -1)
ImGui::SetNextItemOpen(open_action != 0); ImGui::SetNextItemOpen(open_action != 0);
IMGUI_DEMO_MARKER("Tables/Context menus"); IMGUI_DEMO_MARKER("Tables/Context menus");
if (ImGui::TreeNode("Context menus")) if (ImGui::TreeNode("Context menus"))
{ {
HelpMarker("By default, right-clicking over a TableHeadersRow()/TableHeader() line will open the default context-menu.\nUsing ImGuiTableFlags_ContextMenuInBody we also allow right-clicking over columns body."); HelpMarker(
"By default, right-clicking over a TableHeadersRow()/TableHeader() line will open the default context-menu.\n"
"Using ImGuiTableFlags_ContextMenuInBody we also allow right-clicking over columns body.");
static ImGuiTableFlags flags1 = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_ContextMenuInBody; static ImGuiTableFlags flags1 = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_ContextMenuInBody;
PushStyleCompact(); PushStyleCompact();
@@ -5418,7 +5480,9 @@ static void ShowDemoWindowTables()
// [2.1] Right-click on the TableHeadersRow() line to open the default table context menu. // [2.1] Right-click on the TableHeadersRow() line to open the default table context menu.
// [2.2] Right-click on the ".." to open a custom popup // [2.2] Right-click on the ".." to open a custom popup
// [2.3] Right-click in columns to open another custom popup // [2.3] Right-click in columns to open another custom popup
HelpMarker("Demonstrate mixing table context menu (over header), item context button (over button) and custom per-colum context menu (over column body)."); HelpMarker(
"Demonstrate mixing table context menu (over header), item context button (over button) "
"and custom per-colunm context menu (over column body).");
ImGuiTableFlags flags2 = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders; ImGuiTableFlags flags2 = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders;
if (ImGui::BeginTable("table_context_menu_2", COLUMNS_COUNT, flags2)) if (ImGui::BeginTable("table_context_menu_2", COLUMNS_COUNT, flags2))
{ {
@@ -5877,7 +5941,7 @@ static void ShowDemoWindowTables()
// Here we demonstrate marking our data set as needing to be sorted again if we modified a quantity, // Here we demonstrate marking our data set as needing to be sorted again if we modified a quantity,
// and we are currently sorting on the column showing the Quantity. // and we are currently sorting on the column showing the Quantity.
// To avoid triggering a sort while holding the button, we only trigger it when the button has been released. // To avoid triggering a sort while holding the button, we only trigger it when the button has been released.
// You will probably need a more advanced system in your code if you want to automatically sort when a specific entry changes. // You will probably need some extra logic if you want to automatically sort when a specific entry changes.
if (ImGui::TableSetColumnIndex(2)) if (ImGui::TableSetColumnIndex(2))
{ {
if (ImGui::SmallButton("Chop")) { item->Quantity += 1; } if (ImGui::SmallButton("Chop")) { item->Quantity += 1; }
@@ -6165,13 +6229,15 @@ static void ShowDemoWindowInputs()
for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDown(i)) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); } for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDown(i)) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
ImGui::Text("Mouse wheel: %.1f", io.MouseWheel); ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
// We iterate both legacy native range and named ImGuiKey ranges, which is a little odd but this allows displaying the data for old/new backends. // We iterate both legacy native range and named ImGuiKey ranges. This is a little unusual/odd but this allows
// User code should never have to go through such hoops! You can generally iterate between ImGuiKey_NamedKey_BEGIN and ImGuiKey_NamedKey_END. // displaying the data for old/new backends.
// User code should never have to go through such hoops!
// You can generally iterate between ImGuiKey_NamedKey_BEGIN and ImGuiKey_NamedKey_END.
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO #ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
struct funcs { static bool IsLegacyNativeDupe(ImGuiKey) { return false; } }; struct funcs { static bool IsLegacyNativeDupe(ImGuiKey) { return false; } };
ImGuiKey start_key = ImGuiKey_NamedKey_BEGIN; ImGuiKey start_key = ImGuiKey_NamedKey_BEGIN;
#else #else
struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key < 512 && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key >= 0 && key < 512 && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array
ImGuiKey start_key = (ImGuiKey)0; ImGuiKey start_key = (ImGuiKey)0;
#endif #endif
ImGui::Text("Keys down:"); for (ImGuiKey key = start_key; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !ImGui::IsKeyDown(key)) continue; ImGui::SameLine(); ImGui::Text((key < ImGuiKey_NamedKey_BEGIN) ? "\"%s\"" : "\"%s\" %d", ImGui::GetKeyName(key), key); } ImGui::Text("Keys down:"); for (ImGuiKey key = start_key; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !ImGui::IsKeyDown(key)) continue; ImGui::SameLine(); ImGui::Text((key < ImGuiKey_NamedKey_BEGIN) ? "\"%s\"" : "\"%s\" %d", ImGui::GetKeyName(key), key); }
@@ -6205,7 +6271,8 @@ static void ShowDemoWindowInputs()
{ {
HelpMarker( HelpMarker(
"Hovering the colored canvas will override io.WantCaptureXXX fields.\n" "Hovering the colored canvas will override io.WantCaptureXXX fields.\n"
"Notice how normally (when set to none), the value of io.WantCaptureKeyboard would be false when hovering and true when clicking."); "Notice how normally (when set to none), the value of io.WantCaptureKeyboard would be false when hovering "
"and true when clicking.");
static int capture_override_mouse = -1; static int capture_override_mouse = -1;
static int capture_override_keyboard = -1; static int capture_override_keyboard = -1;
const char* capture_override_desc[] = { "None", "Set to false", "Set to true" }; const char* capture_override_desc[] = { "None", "Set to false", "Set to true" };
@@ -6729,6 +6796,12 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
if (!filter.PassFilter(name)) if (!filter.PassFilter(name))
continue; continue;
ImGui::PushID(i); ImGui::PushID(i);
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
if (ImGui::Button("?"))
ImGui::DebugFlashStyleColor((ImGuiCol)i);
ImGui::SetItemTooltip("Flash given color to identify places where it is used.");
ImGui::SameLine();
#endif
ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags); ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0) if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
{ {
@@ -7033,19 +7106,19 @@ struct ExampleAppConsole
{ {
ClearLog(); ClearLog();
for (int i = 0; i < History.Size; i++) for (int i = 0; i < History.Size; i++)
free(History[i]); ImGui::MemFree(History[i]);
} }
// Portable helpers // Portable helpers
static int Stricmp(const char* s1, const char* s2) { int d; while ((d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; } return d; } static int Stricmp(const char* s1, const char* s2) { int d; while ((d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; } return d; }
static int Strnicmp(const char* s1, const char* s2, int n) { int d = 0; while (n > 0 && (d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; n--; } return d; } static int Strnicmp(const char* s1, const char* s2, int n) { int d = 0; while (n > 0 && (d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; n--; } return d; }
static char* Strdup(const char* s) { IM_ASSERT(s); size_t len = strlen(s) + 1; void* buf = malloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)s, len); } static char* Strdup(const char* s) { IM_ASSERT(s); size_t len = strlen(s) + 1; void* buf = ImGui::MemAlloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)s, len); }
static void Strtrim(char* s) { char* str_end = s + strlen(s); while (str_end > s && str_end[-1] == ' ') str_end--; *str_end = 0; } static void Strtrim(char* s) { char* str_end = s + strlen(s); while (str_end > s && str_end[-1] == ' ') str_end--; *str_end = 0; }
void ClearLog() void ClearLog()
{ {
for (int i = 0; i < Items.Size; i++) for (int i = 0; i < Items.Size; i++)
free(Items[i]); ImGui::MemFree(Items[i]);
Items.clear(); Items.clear();
} }
@@ -7211,7 +7284,7 @@ struct ExampleAppConsole
for (int i = History.Size - 1; i >= 0; i--) for (int i = History.Size - 1; i >= 0; i--)
if (Stricmp(History[i], command_line) == 0) if (Stricmp(History[i], command_line) == 0)
{ {
free(History[i]); ImGui::MemFree(History[i]);
History.erase(History.begin() + i); History.erase(History.begin() + i);
break; break;
} }
@@ -8066,6 +8139,9 @@ static void ShowExampleAppCustomRendering(bool* p_open)
const float rounding = sz / 5.0f; const float rounding = sz / 5.0f;
const int circle_segments = circle_segments_override ? circle_segments_override_v : 0; const int circle_segments = circle_segments_override ? circle_segments_override_v : 0;
const int curve_segments = curve_segments_override ? curve_segments_override_v : 0; const int curve_segments = curve_segments_override ? curve_segments_override_v : 0;
const ImVec2 cp3[3] = { ImVec2(0.0f, sz * 0.6f), ImVec2(sz * 0.5f, -sz * 0.4f), ImVec2(sz, sz) }; // Control points for curves
const ImVec2 cp4[4] = { ImVec2(0.0f, 0.0f), ImVec2(sz * 1.3f, sz * 0.3f), ImVec2(sz - sz * 1.3f, sz - sz * 0.3f), ImVec2(sz, sz) };
float x = p.x + 4.0f; float x = p.x + 4.0f;
float y = p.y + 4.0f; float y = p.y + 4.0f;
for (int n = 0; n < 2; n++) for (int n = 0; n < 2; n++)
@@ -8084,17 +8160,23 @@ static void ShowExampleAppCustomRendering(bool* p_open)
draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!) draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!)
draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th); x += sz + spacing; // Diagonal line draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th); x += sz + spacing; // Diagonal line
// Path
draw_list->PathArcTo(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, 3.141592f, 3.141592f * -0.5f);
draw_list->PathStroke(col, ImDrawFlags_None, th);
x += sz + spacing;
// Quadratic Bezier Curve (3 control points) // Quadratic Bezier Curve (3 control points)
ImVec2 cp3[3] = { ImVec2(x, y + sz * 0.6f), ImVec2(x + sz * 0.5f, y - sz * 0.4f), ImVec2(x + sz, y + sz) }; draw_list->AddBezierQuadratic(ImVec2(x + cp3[0].x, y + cp3[0].y), ImVec2(x + cp3[1].x, y + cp3[1].y), ImVec2(x + cp3[2].x, y + cp3[2].y), col, th, curve_segments);
draw_list->AddBezierQuadratic(cp3[0], cp3[1], cp3[2], col, th, curve_segments); x += sz + spacing; x += sz + spacing;
// Cubic Bezier Curve (4 control points) // Cubic Bezier Curve (4 control points)
ImVec2 cp4[4] = { ImVec2(x, y), ImVec2(x + sz * 1.3f, y + sz * 0.3f), ImVec2(x + sz - sz * 1.3f, y + sz - sz * 0.3f), ImVec2(x + sz, y + sz) }; draw_list->AddBezierCubic(ImVec2(x + cp4[0].x, y + cp4[0].y), ImVec2(x + cp4[1].x, y + cp4[1].y), ImVec2(x + cp4[2].x, y + cp4[2].y), ImVec2(x + cp4[3].x, y + cp4[3].y), col, th, curve_segments);
draw_list->AddBezierCubic(cp4[0], cp4[1], cp4[2], cp4[3], col, th, curve_segments);
x = p.x + 4; x = p.x + 4;
y += sz + spacing; y += sz + spacing;
} }
// Filled shapes
draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col, ngon_sides); x += sz + spacing; // N-gon draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col, ngon_sides); x += sz + spacing; // N-gon
draw_list->AddCircleFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col, circle_segments); x += sz + spacing; // Circle draw_list->AddCircleFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col, circle_segments); x += sz + spacing; // Circle
draw_list->AddEllipseFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, sz * 0.3f, col, -0.3f, circle_segments); x += sz + spacing;// Ellipse draw_list->AddEllipseFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, sz * 0.3f, col, -0.3f, circle_segments); x += sz + spacing;// Ellipse
@@ -8106,9 +8188,27 @@ static void ShowExampleAppCustomRendering(bool* p_open)
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + thickness), col); x += sz + spacing; // Horizontal line (faster than AddLine, but only handle integer thickness) draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + thickness), col); x += sz + spacing; // Horizontal line (faster than AddLine, but only handle integer thickness)
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + thickness, y + sz), col); x += spacing * 2.0f;// Vertical line (faster than AddLine, but only handle integer thickness) draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + thickness, y + sz), col); x += spacing * 2.0f;// Vertical line (faster than AddLine, but only handle integer thickness)
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + 1, y + 1), col); x += sz; // Pixel (faster than AddLine) draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + 1, y + 1), col); x += sz; // Pixel (faster than AddLine)
// Path
draw_list->PathArcTo(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, 3.141592f * -0.5f, 3.141592f);
draw_list->PathFillConvex(col);
x += sz + spacing;
// Quadratic Bezier Curve (3 control points)
draw_list->PathLineTo(ImVec2(x + cp3[0].x, y + cp3[0].y));
draw_list->PathBezierQuadraticCurveTo(ImVec2(x + cp3[1].x, y + cp3[1].y), ImVec2(x + cp3[2].x, y + cp3[2].y), curve_segments);
draw_list->PathFillConvex(col);
x += sz + spacing;
// Cubic Bezier Curve (4 control points): this is concave so not drawing it yet
//draw_list->PathLineTo(ImVec2(x + cp4[0].x, y + cp4[0].y));
//draw_list->PathBezierCubicCurveTo(ImVec2(x + cp4[1].x, y + cp4[1].y), ImVec2(x + cp4[2].x, y + cp4[2].y), ImVec2(x + cp4[3].x, y + cp4[3].y), curve_segments);
//draw_list->PathFillConvex(col);
//x += sz + spacing;
draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x + sz, y + sz), IM_COL32(0, 0, 0, 255), IM_COL32(255, 0, 0, 255), IM_COL32(255, 255, 0, 255), IM_COL32(0, 255, 0, 255)); draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x + sz, y + sz), IM_COL32(0, 0, 0, 255), IM_COL32(255, 0, 0, 255), IM_COL32(255, 255, 0, 255), IM_COL32(0, 255, 0, 255));
ImGui::Dummy(ImVec2((sz + spacing) * 11.2f, (sz + spacing) * 3.0f)); ImGui::Dummy(ImVec2((sz + spacing) * 12.2f, (sz + spacing) * 3.0f));
ImGui::PopItemWidth(); ImGui::PopItemWidth();
ImGui::EndTabItem(); ImGui::EndTabItem();
} }

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.90.0 // dear imgui, v1.90.4
// (drawing and font code) // (drawing and font code)
/* /*
@@ -647,7 +647,7 @@ void ImDrawList::PrimReserve(int idx_count, int vtx_count)
_IdxWritePtr = IdxBuffer.Data + idx_buffer_old_size; _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) void ImDrawList::PrimUnreserve(int idx_count, int vtx_count)
{ {
IM_ASSERT_PARANOID(idx_count >= 0 && vtx_count >= 0); IM_ASSERT_PARANOID(idx_count >= 0 && vtx_count >= 0);
@@ -4012,8 +4012,8 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im
} }
else 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, 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, 3); // TR 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) if (p1.x > rect.Min.x + rounding)
{ {
@@ -4032,8 +4032,8 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im
} }
else else
{ {
draw_list->PathArcTo(ImVec2(x1, p0.y + rounding), rounding, -arc1_e, -arc1_b, 3); // TR 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, 3); // BR draw_list->PathArcTo(ImVec2(x1, p1.y - rounding), rounding, +arc1_b, +arc1_e); // BR
} }
} }
draw_list->PathFillConvex(col); draw_list->PathFillConvex(col);
@@ -4231,8 +4231,8 @@ static unsigned int stb_decompress(unsigned char *output, const unsigned char *i
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// ProggyClean.ttf // ProggyClean.ttf
// Copyright (c) 2004, 2005 Tristan Grimmer // Copyright (c) 2004, 2005 Tristan Grimmer
// MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip) // MIT license (see License.txt in http://www.proggyfonts.net/index.php?menu=download)
// Download and more information at http://upperbounds.net // Download and more information at http://www.proggyfonts.net or http://upperboundsinteractive.com/fonts.php
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// File: 'ProggyClean.ttf' (41208 bytes) // File: 'ProggyClean.ttf' (41208 bytes)
// Exported using misc/fonts/binary_to_compressed_c.cpp (with compression + base85 string encoding). // Exported using misc/fonts/binary_to_compressed_c.cpp (with compression + base85 string encoding).

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.90.0 // dear imgui, v1.90.4
// (internal structures/api) // (internal structures/api)
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
@@ -15,6 +15,8 @@ Index of this file:
// [SECTION] Generic helpers // [SECTION] Generic helpers
// [SECTION] ImDrawList support // [SECTION] ImDrawList support
// [SECTION] Widgets support: flags, enums, data structures // [SECTION] Widgets support: flags, enums, data structures
// [SECTION] Data types support
// [SECTION] Popup support
// [SECTION] Inputs support // [SECTION] Inputs support
// [SECTION] Clipper support // [SECTION] Clipper support
// [SECTION] Navigation support // [SECTION] Navigation support
@@ -201,13 +203,13 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
namespace ImStb namespace ImStb
{ {
#undef STB_TEXTEDIT_STRING #undef IMSTB_TEXTEDIT_STRING
#undef STB_TEXTEDIT_CHARTYPE #undef IMSTB_TEXTEDIT_CHARTYPE
#define STB_TEXTEDIT_STRING ImGuiInputTextState #define IMSTB_TEXTEDIT_STRING ImGuiInputTextState
#define STB_TEXTEDIT_CHARTYPE ImWchar #define IMSTB_TEXTEDIT_CHARTYPE ImWchar
#define STB_TEXTEDIT_GETWIDTH_NEWLINE (-1.0f) #define IMSTB_TEXTEDIT_GETWIDTH_NEWLINE (-1.0f)
#define STB_TEXTEDIT_UNDOSTATECOUNT 99 #define IMSTB_TEXTEDIT_UNDOSTATECOUNT 99
#define STB_TEXTEDIT_UNDOCHARCOUNT 999 #define IMSTB_TEXTEDIT_UNDOCHARCOUNT 999
#include "imstb_textedit.h" #include "imstb_textedit.h"
} // namespace ImStb } // namespace ImStb
@@ -235,15 +237,16 @@ namespace ImStb
#else #else
#define IMGUI_DEBUG_LOG(...) ((void)0) #define IMGUI_DEBUG_LOG(...) ((void)0)
#endif #endif
#define IMGUI_DEBUG_LOG_ACTIVEID(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventActiveId) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_ACTIVEID(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventActiveId) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_FOCUS(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFocus) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_FOCUS(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFocus) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_POPUP(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_POPUP(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_NAV(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventNav) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_NAV(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventNav) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_SELECTION(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection)IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_SELECTION(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_CLIPPER(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventClipper) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_CLIPPER(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventClipper) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_IO(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_IO(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_DOCKING(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventDocking) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_INPUTROUTING(...) do{if (g.DebugLogFlags & ImGuiDebugLogFlags_EventInputRouting)IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_VIEWPORT(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventViewport) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_DOCKING(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventDocking) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_VIEWPORT(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventViewport) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
// Static Asserts // Static Asserts
#define IM_STATIC_ASSERT(_COND) static_assert(_COND, "") #define IM_STATIC_ASSERT(_COND) static_assert(_COND, "")
@@ -307,11 +310,11 @@ namespace ImStb
#elif defined(__clang__) #elif defined(__clang__)
#define IM_DEBUG_BREAK() __builtin_debugtrap() #define IM_DEBUG_BREAK() __builtin_debugtrap()
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
#define IM_DEBUG_BREAK() __asm__ volatile("int $0x03") #define IM_DEBUG_BREAK() __asm__ volatile("int3;nop")
#elif defined(__GNUC__) && defined(__thumb__) #elif defined(__GNUC__) && defined(__thumb__)
#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xde01") #define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xde01")
#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) #elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__)
#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xe7f001f0"); #define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xe7f001f0")
#else #else
#define IM_DEBUG_BREAK() IM_ASSERT(0) // It is expected that you define IM_DEBUG_BREAK() into something that will break nicely in a debugger! #define IM_DEBUG_BREAK() IM_ASSERT(0) // It is expected that you define IM_DEBUG_BREAK() into something that will break nicely in a debugger!
#endif #endif
@@ -699,9 +702,6 @@ struct ImPool
int GetBufSize() const { return Buf.Size; } int GetBufSize() const { return Buf.Size; }
int GetMapSize() const { return Map.Data.Size; } // It is the map we need iterate to find valid items, since we don't have "alive" storage anywhere int GetMapSize() const { return Map.Data.Size; } // It is the map we need iterate to find valid items, since we don't have "alive" storage anywhere
T* TryGetMapData(ImPoolIdx n) { int idx = Map.Data[n].val_i; if (idx == -1) return NULL; return GetByIndex(idx); } T* TryGetMapData(ImPoolIdx n) { int idx = Map.Data[n].val_i; if (idx == -1) return NULL; return GetByIndex(idx); }
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
int GetSize() { return GetMapSize(); } // For ImPlot: should use GetMapSize() from (IMGUI_VERSION_NUM >= 18304)
#endif
}; };
// Helper: ImChunkStream<> // Helper: ImChunkStream<>
@@ -845,8 +845,8 @@ enum ImGuiItemStatusFlags_
ImGuiItemStatusFlags_HasDeactivated = 1 << 5, // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag. ImGuiItemStatusFlags_HasDeactivated = 1 << 5, // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag.
ImGuiItemStatusFlags_Deactivated = 1 << 6, // Only valid if ImGuiItemStatusFlags_HasDeactivated is set. ImGuiItemStatusFlags_Deactivated = 1 << 6, // Only valid if ImGuiItemStatusFlags_HasDeactivated is set.
ImGuiItemStatusFlags_HoveredWindow = 1 << 7, // Override the HoveredWindow test to allow cross-window hover testing. ImGuiItemStatusFlags_HoveredWindow = 1 << 7, // Override the HoveredWindow test to allow cross-window hover testing.
ImGuiItemStatusFlags_FocusedByTabbing = 1 << 8, // Set when the Focusable item just got focused by Tabbing (FIXME: to be removed soon) ImGuiItemStatusFlags_Visible = 1 << 8, // [WIP] Set when item is overlapping the current clipping rectangle (Used internally. Please don't use yet: API/system will change as we refactor Itemadd()).
ImGuiItemStatusFlags_Visible = 1 << 9, // [WIP] Set when item is overlapping the current clipping rectangle (Used internally. Please don't use yet: API/system will change as we refactor Itemadd()). ImGuiItemStatusFlags_HasClipRect = 1 << 9, // g.LastItemData.ClipRect is valid
// Additional status + semantic for ImGuiTestEngine // Additional status + semantic for ImGuiTestEngine
#ifdef IMGUI_ENABLE_TEST_ENGINE #ifdef IMGUI_ENABLE_TEST_ENGINE
@@ -995,43 +995,6 @@ enum ImGuiPlotType
ImGuiPlotType_Histogram, ImGuiPlotType_Histogram,
}; };
enum ImGuiPopupPositionPolicy
{
ImGuiPopupPositionPolicy_Default,
ImGuiPopupPositionPolicy_ComboBox,
ImGuiPopupPositionPolicy_Tooltip,
};
struct ImGuiDataVarInfo
{
ImGuiDataType Type;
ImU32 Count; // 1+
ImU32 Offset; // Offset in parent structure
void* GetVarPtr(void* parent) const { return (void*)((unsigned char*)parent + Offset); }
};
struct ImGuiDataTypeTempStorage
{
ImU8 Data[8]; // Can fit any data up to ImGuiDataType_COUNT
};
// Type information associated to one ImGuiDataType. Retrieve with DataTypeGetInfo().
struct ImGuiDataTypeInfo
{
size_t Size; // Size in bytes
const char* Name; // Short descriptive name for the type, for debugging
const char* PrintFmt; // Default printf format for the type
const char* ScanFmt; // Default scanf format for the type
};
// Extend ImGuiDataType_
enum ImGuiDataTypePrivate_
{
ImGuiDataType_String = ImGuiDataType_COUNT + 1,
ImGuiDataType_Pointer,
ImGuiDataType_ID,
};
// Stacked color modifier, backup of modified data so we can restore it // Stacked color modifier, backup of modified data so we can restore it
struct ImGuiColorMod struct ImGuiColorMod
{ {
@@ -1116,7 +1079,7 @@ struct IMGUI_API ImGuiInputTextState
int CurLenW, CurLenA; // we need to maintain our buffer length in both UTF-8 and wchar format. UTF-8 length is valid even if TextA is not. int CurLenW, CurLenA; // we need to maintain our buffer length in both UTF-8 and wchar format. UTF-8 length is valid even if TextA is not.
ImVector<ImWchar> TextW; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer. ImVector<ImWchar> TextW; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
ImVector<char> TextA; // temporary UTF8 buffer for callbacks and other operations. this is not updated in every code-path! size=capacity. ImVector<char> TextA; // temporary UTF8 buffer for callbacks and other operations. this is not updated in every code-path! size=capacity.
ImVector<char> InitialTextA; // backup of end-user buffer at the time of focus (in UTF-8, unaltered) ImVector<char> InitialTextA; // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered)
bool TextAIsValid; // temporary UTF8 buffer is not initially valid before we make the widget active (until then we pull the data from user argument) bool TextAIsValid; // temporary UTF8 buffer is not initially valid before we make the widget active (until then we pull the data from user argument)
int BufCapacityA; // end-user buffer capacity int BufCapacityA; // end-user buffer capacity
float ScrollX; // horizontal scrolling/offset float ScrollX; // horizontal scrolling/offset
@@ -1126,12 +1089,15 @@ struct IMGUI_API ImGuiInputTextState
bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection
bool Edited; // edited this frame bool Edited; // edited this frame
ImGuiInputTextFlags Flags; // copy of InputText() flags. may be used to check if e.g. ImGuiInputTextFlags_Password is set. ImGuiInputTextFlags Flags; // copy of InputText() flags. may be used to check if e.g. ImGuiInputTextFlags_Password is set.
bool ReloadUserBuf; // force a reload of user buf so it may be modified externally. may be automatic in future version.
int ReloadSelectionStart; // POSITIONS ARE IN IMWCHAR units *NOT* UTF-8 this is why this is not exposed yet.
int ReloadSelectionEnd;
ImGuiInputTextState() { memset(this, 0, sizeof(*this)); } ImGuiInputTextState() { memset(this, 0, sizeof(*this)); }
void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); } void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); }
void ClearFreeMemory() { TextW.clear(); TextA.clear(); InitialTextA.clear(); } void ClearFreeMemory() { TextW.clear(); TextA.clear(); InitialTextA.clear(); }
int GetUndoAvailCount() const { return Stb.undostate.undo_point; } int GetUndoAvailCount() const { return Stb.undostate.undo_point; }
int GetRedoAvailCount() const { return STB_TEXTEDIT_UNDOSTATECOUNT - Stb.undostate.redo_point; } int GetRedoAvailCount() const { return IMSTB_TEXTEDIT_UNDOSTATECOUNT - Stb.undostate.redo_point; }
void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation
// Cursor & Selection // Cursor & Selection
@@ -1143,21 +1109,16 @@ struct IMGUI_API ImGuiInputTextState
int GetSelectionStart() const { return Stb.select_start; } int GetSelectionStart() const { return Stb.select_start; }
int GetSelectionEnd() const { return Stb.select_end; } int GetSelectionEnd() const { return Stb.select_end; }
void SelectAll() { Stb.select_start = 0; Stb.cursor = Stb.select_end = CurLenW; Stb.has_preferred_x = 0; } void SelectAll() { Stb.select_start = 0; Stb.cursor = Stb.select_end = CurLenW; Stb.has_preferred_x = 0; }
};
// Storage for current popup stack // Reload user buf (WIP #2890)
struct ImGuiPopupData // If you modify underlying user-passed const char* while active you need to call this (InputText V2 may lift this)
{ // strcpy(my_buf, "hello");
ImGuiID PopupId; // Set on OpenPopup() // if (ImGuiInputTextState* state = ImGui::GetInputTextState(id)) // id may be ImGui::GetItemID() is last item
ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() // state->ReloadUserBufAndSelectAll();
ImGuiWindow* BackupNavWindow;// Set on OpenPopup(), a NavWindow that will be restored on popup close void ReloadUserBufAndSelectAll() { ReloadUserBuf = true; ReloadSelectionStart = 0; ReloadSelectionEnd = INT_MAX; }
int ParentNavLayer; // Resolved on BeginPopup(). Actually a ImGuiNavLayer type (declared down below), initialized to -1 which is not part of an enum, but serves well-enough as "not any of layers" value void ReloadUserBufAndKeepSelection() { ReloadUserBuf = true; ReloadSelectionStart = Stb.select_start; ReloadSelectionEnd = Stb.select_end; }
int OpenFrameCount; // Set on OpenPopup() void ReloadUserBufAndMoveToEnd() { ReloadUserBuf = true; ReloadSelectionStart = ReloadSelectionEnd = INT_MAX; }
ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items)
ImVec2 OpenPopupPos; // Set on OpenPopup(), preferred popup position (typically == OpenMousePos when using mouse)
ImVec2 OpenMousePos; // Set on OpenPopup(), copy of mouse position at the time of opening popup
ImGuiPopupData() { memset(this, 0, sizeof(*this)); ParentNavLayer = OpenFrameCount = -1; }
}; };
enum ImGuiNextWindowDataFlags_ enum ImGuiNextWindowDataFlags_
@@ -1212,9 +1173,10 @@ typedef ImS64 ImGuiSelectionUserData;
enum ImGuiNextItemDataFlags_ enum ImGuiNextItemDataFlags_
{ {
ImGuiNextItemDataFlags_None = 0, ImGuiNextItemDataFlags_None = 0,
ImGuiNextItemDataFlags_HasWidth = 1 << 0, ImGuiNextItemDataFlags_HasWidth = 1 << 0,
ImGuiNextItemDataFlags_HasOpen = 1 << 1, ImGuiNextItemDataFlags_HasOpen = 1 << 1,
ImGuiNextItemDataFlags_HasShortcut = 1 << 2,
}; };
struct ImGuiNextItemData struct ImGuiNextItemData
@@ -1222,10 +1184,11 @@ struct ImGuiNextItemData
ImGuiNextItemDataFlags Flags; ImGuiNextItemDataFlags Flags;
ImGuiItemFlags ItemFlags; // Currently only tested/used for ImGuiItemFlags_AllowOverlap. ImGuiItemFlags ItemFlags; // Currently only tested/used for ImGuiItemFlags_AllowOverlap.
// Non-flags members are NOT cleared by ItemAdd() meaning they are still valid during NavProcessItem() // Non-flags members are NOT cleared by ItemAdd() meaning they are still valid during NavProcessItem()
float Width; // Set by SetNextItemWidth()
ImGuiSelectionUserData SelectionUserData; // Set by SetNextItemSelectionUserData() (note that NULL/0 is a valid value, we use -1 == ImGuiSelectionUserData_Invalid to mark invalid values) ImGuiSelectionUserData SelectionUserData; // Set by SetNextItemSelectionUserData() (note that NULL/0 is a valid value, we use -1 == ImGuiSelectionUserData_Invalid to mark invalid values)
ImGuiCond OpenCond; float Width; // Set by SetNextItemWidth()
ImGuiKeyChord Shortcut; // Set by SetNextItemShortcut()
bool OpenVal; // Set by SetNextItemOpen() bool OpenVal; // Set by SetNextItemOpen()
ImGuiCond OpenCond : 8;
ImGuiNextItemData() { memset(this, 0, sizeof(*this)); SelectionUserData = -1; } ImGuiNextItemData() { memset(this, 0, sizeof(*this)); SelectionUserData = -1; }
inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()! inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()!
@@ -1239,7 +1202,9 @@ struct ImGuiLastItemData
ImGuiItemStatusFlags StatusFlags; // See ImGuiItemStatusFlags_ ImGuiItemStatusFlags StatusFlags; // See ImGuiItemStatusFlags_
ImRect Rect; // Full rectangle ImRect Rect; // Full rectangle
ImRect NavRect; // Navigation scoring rectangle (not displayed) ImRect NavRect; // Navigation scoring rectangle (not displayed)
ImRect DisplayRect; // Display rectangle (only if ImGuiItemStatusFlags_HasDisplayRect is set) // Rarely used fields are not explicitly cleared, only valid when the corresponding ImGuiItemStatusFlags is set.
ImRect DisplayRect; // Display rectangle (ONLY VALID IF ImGuiItemStatusFlags_HasDisplayRect is set)
ImRect ClipRect; // Clip rectangle at the time of submitting item (ONLY VALID IF ImGuiItemStatusFlags_HasClipRect is set)
ImGuiLastItemData() { memset(this, 0, sizeof(*this)); } ImGuiLastItemData() { memset(this, 0, sizeof(*this)); }
}; };
@@ -1295,6 +1260,66 @@ struct ImGuiPtrOrIndex
ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; } ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; }
}; };
//-----------------------------------------------------------------------------
// [SECTION] Data types support
//-----------------------------------------------------------------------------
struct ImGuiDataVarInfo
{
ImGuiDataType Type;
ImU32 Count; // 1+
ImU32 Offset; // Offset in parent structure
void* GetVarPtr(void* parent) const { return (void*)((unsigned char*)parent + Offset); }
};
struct ImGuiDataTypeTempStorage
{
ImU8 Data[8]; // Can fit any data up to ImGuiDataType_COUNT
};
// Type information associated to one ImGuiDataType. Retrieve with DataTypeGetInfo().
struct ImGuiDataTypeInfo
{
size_t Size; // Size in bytes
const char* Name; // Short descriptive name for the type, for debugging
const char* PrintFmt; // Default printf format for the type
const char* ScanFmt; // Default scanf format for the type
};
// Extend ImGuiDataType_
enum ImGuiDataTypePrivate_
{
ImGuiDataType_String = ImGuiDataType_COUNT + 1,
ImGuiDataType_Pointer,
ImGuiDataType_ID,
};
//-----------------------------------------------------------------------------
// [SECTION] Popup support
//-----------------------------------------------------------------------------
enum ImGuiPopupPositionPolicy
{
ImGuiPopupPositionPolicy_Default,
ImGuiPopupPositionPolicy_ComboBox,
ImGuiPopupPositionPolicy_Tooltip,
};
// Storage for popup stacks (g.OpenPopupStack and g.BeginPopupStack)
struct ImGuiPopupData
{
ImGuiID PopupId; // Set on OpenPopup()
ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
ImGuiWindow* BackupNavWindow;// Set on OpenPopup(), a NavWindow that will be restored on popup close
int ParentNavLayer; // Resolved on BeginPopup(). Actually a ImGuiNavLayer type (declared down below), initialized to -1 which is not part of an enum, but serves well-enough as "not any of layers" value
int OpenFrameCount; // Set on OpenPopup()
ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items)
ImVec2 OpenPopupPos; // Set on OpenPopup(), preferred popup position (typically == OpenMousePos when using mouse)
ImVec2 OpenMousePos; // Set on OpenPopup(), copy of mouse position at the time of opening popup
ImGuiPopupData() { memset(this, 0, sizeof(*this)); ParentNavLayer = OpenFrameCount = -1; }
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Inputs support // [SECTION] Inputs support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -1388,11 +1413,12 @@ struct ImGuiKeyRoutingData
{ {
ImGuiKeyRoutingIndex NextEntryIndex; ImGuiKeyRoutingIndex NextEntryIndex;
ImU16 Mods; // Technically we'd only need 4-bits but for simplify we store ImGuiMod_ values which need 16-bits. ImGuiMod_Shortcut is already translated to Ctrl/Super. ImU16 Mods; // Technically we'd only need 4-bits but for simplify we store ImGuiMod_ values which need 16-bits. ImGuiMod_Shortcut is already translated to Ctrl/Super.
ImU8 RoutingCurrScore; // [DEBUG] For debug display
ImU8 RoutingNextScore; // Lower is better (0: perfect score) ImU8 RoutingNextScore; // Lower is better (0: perfect score)
ImGuiID RoutingCurr; ImGuiID RoutingCurr;
ImGuiID RoutingNext; ImGuiID RoutingNext;
ImGuiKeyRoutingData() { NextEntryIndex = -1; Mods = 0; RoutingNextScore = 255; RoutingCurr = RoutingNext = ImGuiKeyOwner_None; } ImGuiKeyRoutingData() { NextEntryIndex = -1; Mods = 0; RoutingCurrScore = RoutingNextScore = 255; RoutingCurr = RoutingNext = ImGuiKeyOwner_None; }
}; };
// Routing table: maintain a desired owner for each possible key-chord (key + mods), and setup owner in NewFrame() when mods are matching. // Routing table: maintain a desired owner for each possible key-chord (key + mods), and setup owner in NewFrame() when mods are matching.
@@ -1420,49 +1446,69 @@ struct ImGuiKeyOwnerData
}; };
// Flags for extended versions of IsKeyPressed(), IsMouseClicked(), Shortcut(), SetKeyOwner(), SetItemKeyOwner() // Flags for extended versions of IsKeyPressed(), IsMouseClicked(), Shortcut(), SetKeyOwner(), SetItemKeyOwner()
// Don't mistake with ImGuiInputTextFlags! (for ImGui::InputText() function) // Don't mistake with ImGuiInputTextFlags! (which is for ImGui::InputText() function)
enum ImGuiInputFlags_ enum ImGuiInputFlags_
{ {
// Flags for IsKeyPressed(), IsMouseClicked(), Shortcut() // Flags for IsKeyPressed(), IsKeyChordPressed(), IsMouseClicked(), Shortcut()
ImGuiInputFlags_None = 0, ImGuiInputFlags_None = 0,
ImGuiInputFlags_Repeat = 1 << 0, // Return true on successive repeats. Default for legacy IsKeyPressed(). NOT Default for legacy IsMouseClicked(). MUST BE == 1.
// Repeat mode
ImGuiInputFlags_Repeat = 1 << 0, // Enable repeat. Return true on successive repeats. Default for legacy IsKeyPressed(). NOT Default for legacy IsMouseClicked(). MUST BE == 1.
ImGuiInputFlags_RepeatRateDefault = 1 << 1, // Repeat rate: Regular (default) ImGuiInputFlags_RepeatRateDefault = 1 << 1, // Repeat rate: Regular (default)
ImGuiInputFlags_RepeatRateNavMove = 1 << 2, // Repeat rate: Fast ImGuiInputFlags_RepeatRateNavMove = 1 << 2, // Repeat rate: Fast
ImGuiInputFlags_RepeatRateNavTweak = 1 << 3, // Repeat rate: Faster ImGuiInputFlags_RepeatRateNavTweak = 1 << 3, // Repeat rate: Faster
ImGuiInputFlags_RepeatRateMask_ = ImGuiInputFlags_RepeatRateDefault | ImGuiInputFlags_RepeatRateNavMove | ImGuiInputFlags_RepeatRateNavTweak,
// Repeat mode: Specify when repeating key pressed can be interrupted.
// In theory ImGuiInputFlags_RepeatUntilOtherKeyPress may be a desirable default, but it would break too many behavior so everything is opt-in.
ImGuiInputFlags_RepeatUntilRelease = 1 << 4, // Stop repeating when released (default for all functions except Shortcut). This only exists to allow overriding Shortcut() default behavior.
ImGuiInputFlags_RepeatUntilKeyModsChange = 1 << 5, // Stop repeating when released OR if keyboard mods are changed (default for Shortcut)
ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone = 1 << 6, // Stop repeating when released OR if keyboard mods are leaving the None state. Allows going from Mod+Key to Key by releasing Mod.
ImGuiInputFlags_RepeatUntilOtherKeyPress = 1 << 7, // Stop repeating when released OR if any other keyboard key is pressed during the repeat
// Flags for SetItemKeyOwner() // Flags for SetItemKeyOwner()
ImGuiInputFlags_CondHovered = 1 << 4, // Only set if item is hovered (default to both) ImGuiInputFlags_CondHovered = 1 << 8, // Only set if item is hovered (default to both)
ImGuiInputFlags_CondActive = 1 << 5, // Only set if item is active (default to both) ImGuiInputFlags_CondActive = 1 << 9, // Only set if item is active (default to both)
ImGuiInputFlags_CondDefault_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive, ImGuiInputFlags_CondDefault_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive,
ImGuiInputFlags_CondMask_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive,
// Flags for SetKeyOwner(), SetItemKeyOwner() // Flags for SetKeyOwner(), SetItemKeyOwner()
ImGuiInputFlags_LockThisFrame = 1 << 6, // Access to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared at end of frame. This is useful to make input-owner-aware code steal keys from non-input-owner-aware code. // Locking is useful to make input-owner-aware code steal keys from non-input-owner-aware code. If all code is input-owner-aware locking would never be necessary.
ImGuiInputFlags_LockUntilRelease = 1 << 7, // Access to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared when the key is released or at end of each frame if key is released. This is useful to make input-owner-aware code steal keys from non-input-owner-aware code. ImGuiInputFlags_LockThisFrame = 1 << 10, // Further accesses to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared at end of frame.
ImGuiInputFlags_LockUntilRelease = 1 << 11, // Further accesses to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared when the key is released or at end of each frame if key is released.
// Routing policies for Shortcut() + low-level SetShortcutRouting() // Routing policies for Shortcut() + low-level SetShortcutRouting()
// - The general idea is that several callers register interest in a shortcut, and only one owner gets it. // - The general idea is that several callers register interest in a shortcut, and only one owner gets it.
// - When a policy (other than _RouteAlways) is set, Shortcut() will register itself with SetShortcutRouting(), // Parent -> call Shortcut(Ctrl+S) // When Parent is focused, Parent gets the shortcut.
// Child1 -> call Shortcut(Ctrl+S) // When Child1 is focused, Child1 gets the shortcut (Child1 overrides Parent shortcuts)
// Child2 -> no call // When Child2 is focused, Parent gets the shortcut.
// The whole system is order independent, so if Child1 does it calls before Parent results will be identical.
// This is an important property as it facilitate working with foreign code or larger codebase.
// - Visualize registered routes in 'Metrics->Inputs' and submitted routes in 'Debug Log->InputRouting'.
// - When a policy (except for _RouteAlways *) is set, Shortcut() will register itself with SetShortcutRouting(),
// allowing the system to decide where to route the input among other route-aware calls. // allowing the system to decide where to route the input among other route-aware calls.
// - Shortcut() uses ImGuiInputFlags_RouteFocused by default: meaning that a simple Shortcut() poll // (* Using ImGuiInputFlags_RouteAlways is roughly equivalent to calling IsKeyChordPressed(key)).
// will register a route and only succeed when parent window is in the focus stack and if no-one // - Shortcut() uses ImGuiInputFlags_RouteFocused by default. Meaning that a Shortcut() call will register
// with a higher priority is claiming the shortcut. // a route and only succeed when parent window is in the focus-stack and if no-one with a higher priority
// - Using ImGuiInputFlags_RouteAlways is roughly equivalent to doing e.g. IsKeyPressed(key) + testing mods. // is claiming the same shortcut.
// - You can chain two unrelated windows in the focus stack using SetWindowParentWindowForFocusRoute().
// - Priorities: GlobalHigh > Focused (when owner is active item) > Global > Focused (when focused window) > GlobalLow. // - Priorities: GlobalHigh > Focused (when owner is active item) > Global > Focused (when focused window) > GlobalLow.
// - Can select only 1 policy among all available. // - Can select only 1 policy among all available.
ImGuiInputFlags_RouteFocused = 1 << 8, // (Default) Register focused route: Accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window. ImGuiInputFlags_RouteFocused = 1 << 12, // (Default) Honor focus route: Accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window.
ImGuiInputFlags_RouteGlobalLow = 1 << 9, // Register route globally (lowest priority: unless a focused window or active item registered the route) -> recommended Global priority. ImGuiInputFlags_RouteGlobalLow = 1 << 13, // Register route globally (lowest priority: unless a focused window or active item registered the route) -> recommended Global priority IF you need a Global priority.
ImGuiInputFlags_RouteGlobal = 1 << 10, // Register route globally (medium priority: unless an active item registered the route, e.g. CTRL+A registered by InputText). ImGuiInputFlags_RouteGlobal = 1 << 14, // Register route globally (medium priority: unless an active item registered the route, e.g. CTRL+A registered by InputText will take priority over this).
ImGuiInputFlags_RouteGlobalHigh = 1 << 11, // Register route globally (highest priority: unlikely you need to use that: will interfere with every active items) ImGuiInputFlags_RouteGlobalHigh = 1 << 15, // Register route globally (higher priority: unlikely you need to use that: will interfere with every active items, e.g. CTRL+A registered by InputText will be overriden by this)
ImGuiInputFlags_RouteMask_ = ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteGlobalLow | ImGuiInputFlags_RouteGlobalHigh, // _Always not part of this! ImGuiInputFlags_RouteAlways = 1 << 16, // Do not register route, poll keys directly.
ImGuiInputFlags_RouteAlways = 1 << 12, // Do not register route, poll keys directly. // Routing polices: extra options
ImGuiInputFlags_RouteUnlessBgFocused= 1 << 13, // Global routes will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications. ImGuiInputFlags_RouteUnlessBgFocused= 1 << 17, // Global routes will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications.
ImGuiInputFlags_RouteExtraMask_ = ImGuiInputFlags_RouteAlways | ImGuiInputFlags_RouteUnlessBgFocused,
// [Internal] Mask of which function support which flags // [Internal] Mask of which function support which flags
ImGuiInputFlags_SupportedByIsKeyPressed = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_, ImGuiInputFlags_RepeatRateMask_ = ImGuiInputFlags_RepeatRateDefault | ImGuiInputFlags_RepeatRateNavMove | ImGuiInputFlags_RepeatRateNavTweak,
ImGuiInputFlags_SupportedByShortcut = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RouteMask_ | ImGuiInputFlags_RouteExtraMask_, ImGuiInputFlags_RepeatUntilMask_ = ImGuiInputFlags_RepeatUntilRelease | ImGuiInputFlags_RepeatUntilKeyModsChange | ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone | ImGuiInputFlags_RepeatUntilOtherKeyPress,
ImGuiInputFlags_RepeatMask_ = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_,
ImGuiInputFlags_CondMask_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive,
ImGuiInputFlags_RouteMask_ = ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteGlobalLow | ImGuiInputFlags_RouteGlobalHigh, // _Always not part of this!
ImGuiInputFlags_SupportedByIsKeyPressed = ImGuiInputFlags_RepeatMask_,
ImGuiInputFlags_SupportedByIsMouseClicked = ImGuiInputFlags_Repeat,
ImGuiInputFlags_SupportedByShortcut = ImGuiInputFlags_RepeatMask_ | ImGuiInputFlags_RouteMask_ | ImGuiInputFlags_RouteAlways | ImGuiInputFlags_RouteUnlessBgFocused,
ImGuiInputFlags_SupportedBySetKeyOwner = ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease, ImGuiInputFlags_SupportedBySetKeyOwner = ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease,
ImGuiInputFlags_SupportedBySetItemKeyOwner = ImGuiInputFlags_SupportedBySetKeyOwner | ImGuiInputFlags_CondMask_, ImGuiInputFlags_SupportedBySetItemKeyOwner = ImGuiInputFlags_SupportedBySetKeyOwner | ImGuiInputFlags_CondMask_,
}; };
@@ -1507,6 +1553,8 @@ enum ImGuiActivateFlags_
ImGuiActivateFlags_PreferInput = 1 << 0, // Favor activation that requires keyboard text input (e.g. for Slider/Drag). Default for Enter key. ImGuiActivateFlags_PreferInput = 1 << 0, // Favor activation that requires keyboard text input (e.g. for Slider/Drag). Default for Enter key.
ImGuiActivateFlags_PreferTweak = 1 << 1, // Favor activation for tweaking with arrows or gamepad (e.g. for Slider/Drag). Default for Space key and if keyboard is not used. ImGuiActivateFlags_PreferTweak = 1 << 1, // Favor activation for tweaking with arrows or gamepad (e.g. for Slider/Drag). Default for Space key and if keyboard is not used.
ImGuiActivateFlags_TryToPreserveState = 1 << 2, // Request widget to preserve state if it can (e.g. InputText will try to preserve cursor/selection) ImGuiActivateFlags_TryToPreserveState = 1 << 2, // Request widget to preserve state if it can (e.g. InputText will try to preserve cursor/selection)
ImGuiActivateFlags_FromTabbing = 1 << 3, // Activation requested by a tabbing request
ImGuiActivateFlags_FromShortcut = 1 << 4, // Activation requested by an item shortcut via SetNextItemShortcut() function.
}; };
// Early work-in-progress API for ScrollToItem() // Early work-in-progress API for ScrollToItem()
@@ -1527,8 +1575,7 @@ enum ImGuiScrollFlags_
enum ImGuiNavHighlightFlags_ enum ImGuiNavHighlightFlags_
{ {
ImGuiNavHighlightFlags_None = 0, ImGuiNavHighlightFlags_None = 0,
ImGuiNavHighlightFlags_TypeDefault = 1 << 0, ImGuiNavHighlightFlags_Compact = 1 << 1, // Compact highlight, no padding
ImGuiNavHighlightFlags_TypeThin = 1 << 1,
ImGuiNavHighlightFlags_AlwaysDraw = 1 << 2, // Draw rectangular highlight if (g.NavId == id) _even_ when using the mouse. ImGuiNavHighlightFlags_AlwaysDraw = 1 << 2, // Draw rectangular highlight if (g.NavId == id) _even_ when using the mouse.
ImGuiNavHighlightFlags_NoRounding = 1 << 3, ImGuiNavHighlightFlags_NoRounding = 1 << 3,
}; };
@@ -1577,6 +1624,12 @@ struct ImGuiNavItemData
void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; SelectionUserData = -1; DistBox = DistCenter = DistAxial = FLT_MAX; } void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; SelectionUserData = -1; DistBox = DistCenter = DistAxial = FLT_MAX; }
}; };
struct ImGuiFocusScopeData
{
ImGuiID ID;
ImGuiID WindowID;
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Typing-select support // [SECTION] Typing-select support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -1618,7 +1671,7 @@ struct IMGUI_API ImGuiTypingSelectState
// [SECTION] Columns support // [SECTION] Columns support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Flags for internal's BeginColumns(). Prefix using BeginTable() nowadays! // Flags for internal's BeginColumns(). This is an obsolete API. Prefer using BeginTable() nowadays!
enum ImGuiOldColumnFlags_ enum ImGuiOldColumnFlags_
{ {
ImGuiOldColumnFlags_None = 0, ImGuiOldColumnFlags_None = 0,
@@ -1626,16 +1679,16 @@ enum ImGuiOldColumnFlags_
ImGuiOldColumnFlags_NoResize = 1 << 1, // Disable resizing columns when clicking on the dividers ImGuiOldColumnFlags_NoResize = 1 << 1, // Disable resizing columns when clicking on the dividers
ImGuiOldColumnFlags_NoPreserveWidths = 1 << 2, // Disable column width preservation when adjusting columns ImGuiOldColumnFlags_NoPreserveWidths = 1 << 2, // Disable column width preservation when adjusting columns
ImGuiOldColumnFlags_NoForceWithinWindow = 1 << 3, // Disable forcing columns to fit within window ImGuiOldColumnFlags_NoForceWithinWindow = 1 << 3, // Disable forcing columns to fit within window
ImGuiOldColumnFlags_GrowParentContentsSize = 1 << 4, // (WIP) Restore pre-1.51 behavior of extending the parent window contents size but _without affecting the columns width at all_. Will eventually remove. ImGuiOldColumnFlags_GrowParentContentsSize = 1 << 4, // Restore pre-1.51 behavior of extending the parent window contents size but _without affecting the columns width at all_. Will eventually remove.
// Obsolete names (will be removed) // Obsolete names (will be removed)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiColumnsFlags_None = ImGuiOldColumnFlags_None, //ImGuiColumnsFlags_None = ImGuiOldColumnFlags_None,
ImGuiColumnsFlags_NoBorder = ImGuiOldColumnFlags_NoBorder, //ImGuiColumnsFlags_NoBorder = ImGuiOldColumnFlags_NoBorder,
ImGuiColumnsFlags_NoResize = ImGuiOldColumnFlags_NoResize, //ImGuiColumnsFlags_NoResize = ImGuiOldColumnFlags_NoResize,
ImGuiColumnsFlags_NoPreserveWidths = ImGuiOldColumnFlags_NoPreserveWidths, //ImGuiColumnsFlags_NoPreserveWidths = ImGuiOldColumnFlags_NoPreserveWidths,
ImGuiColumnsFlags_NoForceWithinWindow = ImGuiOldColumnFlags_NoForceWithinWindow, //ImGuiColumnsFlags_NoForceWithinWindow = ImGuiOldColumnFlags_NoForceWithinWindow,
ImGuiColumnsFlags_GrowParentContentsSize = ImGuiOldColumnFlags_GrowParentContentsSize, //ImGuiColumnsFlags_GrowParentContentsSize = ImGuiOldColumnFlags_GrowParentContentsSize,
#endif #endif
}; };
@@ -1702,6 +1755,7 @@ enum ImGuiDockNodeFlagsPrivate_
ImGuiDockNodeFlags_NoCloseButton = 1 << 15, // Saved // Disable close button ImGuiDockNodeFlags_NoCloseButton = 1 << 15, // Saved // Disable close button
ImGuiDockNodeFlags_NoResizeX = 1 << 16, // // ImGuiDockNodeFlags_NoResizeX = 1 << 16, // //
ImGuiDockNodeFlags_NoResizeY = 1 << 17, // // ImGuiDockNodeFlags_NoResizeY = 1 << 17, // //
ImGuiDockNodeFlags_DockedWindowsInFocusRoute= 1 << 18, // // Any docked window will be automatically be focus-route chained (window->ParentWindowForFocusRoute set to this) so Shortcut() in this window can run when any docked window is focused.
// Disable docking/undocking actions in this dockspace or individual node (existing docked nodes will be preserved) // Disable docking/undocking actions in this dockspace or individual node (existing docked nodes will be preserved)
// Those are not exposed in public because the desirable sharing/inheriting/copy-flag-on-split behaviors are quite difficult to design and understand. // Those are not exposed in public because the desirable sharing/inheriting/copy-flag-on-split behaviors are quite difficult to design and understand.
// The two public flags ImGuiDockNodeFlags_NoDockingOverCentralNode/ImGuiDockNodeFlags_NoDockingSplit don't have those issues. // The two public flags ImGuiDockNodeFlags_NoDockingOverCentralNode/ImGuiDockNodeFlags_NoDockingSplit don't have those issues.
@@ -1950,19 +2004,21 @@ struct ImGuiLocEntry
enum ImGuiDebugLogFlags_ enum ImGuiDebugLogFlags_
{ {
// Event types // Event types
ImGuiDebugLogFlags_None = 0, ImGuiDebugLogFlags_None = 0,
ImGuiDebugLogFlags_EventActiveId = 1 << 0, ImGuiDebugLogFlags_EventActiveId = 1 << 0,
ImGuiDebugLogFlags_EventFocus = 1 << 1, ImGuiDebugLogFlags_EventFocus = 1 << 1,
ImGuiDebugLogFlags_EventPopup = 1 << 2, ImGuiDebugLogFlags_EventPopup = 1 << 2,
ImGuiDebugLogFlags_EventNav = 1 << 3, ImGuiDebugLogFlags_EventNav = 1 << 3,
ImGuiDebugLogFlags_EventClipper = 1 << 4, ImGuiDebugLogFlags_EventClipper = 1 << 4,
ImGuiDebugLogFlags_EventSelection = 1 << 5, ImGuiDebugLogFlags_EventSelection = 1 << 5,
ImGuiDebugLogFlags_EventIO = 1 << 6, ImGuiDebugLogFlags_EventIO = 1 << 6,
ImGuiDebugLogFlags_EventDocking = 1 << 7, ImGuiDebugLogFlags_EventInputRouting = 1 << 7,
ImGuiDebugLogFlags_EventViewport = 1 << 8, ImGuiDebugLogFlags_EventDocking = 1 << 8,
ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO | ImGuiDebugLogFlags_EventDocking | ImGuiDebugLogFlags_EventViewport, ImGuiDebugLogFlags_EventViewport = 1 << 9,
ImGuiDebugLogFlags_OutputToTTY = 1 << 10, // Also send output to TTY
ImGuiDebugLogFlags_OutputToTestEngine = 1 << 11,// Also send output to Test Engine ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO | ImGuiDebugLogFlags_EventInputRouting | ImGuiDebugLogFlags_EventDocking | ImGuiDebugLogFlags_EventViewport,
ImGuiDebugLogFlags_OutputToTTY = 1 << 20, // Also send output to TTY
ImGuiDebugLogFlags_OutputToTestEngine = 1 << 21, // Also send output to Test Engine
}; };
struct ImGuiDebugAllocEntry struct ImGuiDebugAllocEntry
@@ -1991,10 +2047,13 @@ struct ImGuiMetricsConfig
bool ShowTablesRects = false; bool ShowTablesRects = false;
bool ShowDrawCmdMesh = true; bool ShowDrawCmdMesh = true;
bool ShowDrawCmdBoundingBoxes = true; bool ShowDrawCmdBoundingBoxes = true;
bool ShowTextEncodingViewer = false;
bool ShowAtlasTintedWithTextColor = false; bool ShowAtlasTintedWithTextColor = false;
bool ShowDockingNodes = false; bool ShowDockingNodes = false;
int ShowWindowsRectsType = -1; int ShowWindowsRectsType = -1;
int ShowTablesRectsType = -1; int ShowTablesRectsType = -1;
int HighlightMonitorIdx = -1;
ImGuiID HighlightViewportID = 0;
}; };
struct ImGuiStackLevelInfo struct ImGuiStackLevelInfo
@@ -2082,6 +2141,7 @@ struct ImGuiContext
ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow* ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow*
int WindowsActiveCount; // Number of unique windows submitted by frame int WindowsActiveCount; // Number of unique windows submitted by frame
ImVec2 WindowsHoverPadding; // Padding around resizable windows for which hovering on counts as hovering the window == ImMax(style.TouchExtraPadding, WINDOWS_HOVER_PADDING) ImVec2 WindowsHoverPadding; // Padding around resizable windows for which hovering on counts as hovering the window == ImMax(style.TouchExtraPadding, WINDOWS_HOVER_PADDING)
ImGuiID DebugBreakInWindow; // Set to break in Begin() call.
ImGuiWindow* CurrentWindow; // Window being drawn into ImGuiWindow* CurrentWindow; // Window being drawn into
ImGuiWindow* HoveredWindow; // Window the mouse is hovering. Will typically catch mouse inputs. ImGuiWindow* HoveredWindow; // Window the mouse is hovering. Will typically catch mouse inputs.
ImGuiWindow* HoveredWindowUnderMovingWindow; // Hovered window ignoring MovingWindow. Only set if MovingWindow is set. ImGuiWindow* HoveredWindowUnderMovingWindow; // Hovered window ignoring MovingWindow. Only set if MovingWindow is set.
@@ -2111,10 +2171,11 @@ struct ImGuiContext
bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch. bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch.
bool ActiveIdHasBeenEditedBefore; // Was the value associated to the widget Edited over the course of the Active state. bool ActiveIdHasBeenEditedBefore; // Was the value associated to the widget Edited over the course of the Active state.
bool ActiveIdHasBeenEditedThisFrame; bool ActiveIdHasBeenEditedThisFrame;
bool ActiveIdFromShortcut;
int ActiveIdMouseButton : 8;
ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior)
ImGuiWindow* ActiveIdWindow; ImGuiWindow* ActiveIdWindow;
ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad
int ActiveIdMouseButton;
ImGuiID ActiveIdPreviousFrame; ImGuiID ActiveIdPreviousFrame;
bool ActiveIdPreviousFrameIsAlive; bool ActiveIdPreviousFrameIsAlive;
bool ActiveIdPreviousFrameHasBeenEditedBefore; bool ActiveIdPreviousFrameHasBeenEditedBefore;
@@ -2126,17 +2187,22 @@ struct ImGuiContext
// - The idea is that instead of "eating" a given key, we can link to an owner. // - The idea is that instead of "eating" a given key, we can link to an owner.
// - Input query can then read input by specifying ImGuiKeyOwner_Any (== 0), ImGuiKeyOwner_None (== -1) or a custom ID. // - Input query can then read input by specifying ImGuiKeyOwner_Any (== 0), ImGuiKeyOwner_None (== -1) or a custom ID.
// - Routing is requested ahead of time for a given chord (Key + Mods) and granted in NewFrame(). // - Routing is requested ahead of time for a given chord (Key + Mods) and granted in NewFrame().
double LastKeyModsChangeTime; // Record the last time key mods changed (affect repeat delay when using shortcut logic)
double LastKeyModsChangeFromNoneTime; // Record the last time key mods changed away from being 0 (affect repeat delay when using shortcut logic)
double LastKeyboardKeyPressTime; // Record the last time a keyboard key (ignore mouse/gamepad ones) was pressed.
ImBitArrayForNamedKeys KeysMayBeCharInput; // Lookup to tell if a key can emit char input, see IsKeyChordPotentiallyCharInput(). sizeof() = 20 bytes
ImGuiKeyOwnerData KeysOwnerData[ImGuiKey_NamedKey_COUNT]; ImGuiKeyOwnerData KeysOwnerData[ImGuiKey_NamedKey_COUNT];
ImGuiKeyRoutingTable KeysRoutingTable; ImGuiKeyRoutingTable KeysRoutingTable;
ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it) ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it)
bool ActiveIdUsingAllKeyboardKeys; // Active widget will want to read all keyboard keys inputs. (FIXME: This is a shortcut for not taking ownership of 100+ keys but perhaps best to not have the inconsistency) bool ActiveIdUsingAllKeyboardKeys; // Active widget will want to read all keyboard keys inputs. (FIXME: This is a shortcut for not taking ownership of 100+ keys but perhaps best to not have the inconsistency)
ImGuiKeyChord DebugBreakInShortcutRouting; // Set to break in SetShortcutRouting()/Shortcut() calls.
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
ImU32 ActiveIdUsingNavInputMask; // If you used this. Since (IMGUI_VERSION_NUM >= 18804) : 'g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel);' becomes 'SetKeyOwner(ImGuiKey_Escape, g.ActiveId) and/or SetKeyOwner(ImGuiKey_NavGamepadCancel, g.ActiveId);' ImU32 ActiveIdUsingNavInputMask; // If you used this. Since (IMGUI_VERSION_NUM >= 18804) : 'g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel);' becomes 'SetKeyOwner(ImGuiKey_Escape, g.ActiveId) and/or SetKeyOwner(ImGuiKey_NavGamepadCancel, g.ActiveId);'
#endif #endif
// Next window/item data // Next window/item data
ImGuiID CurrentFocusScopeId; // == g.FocusScopeStack.back() ImGuiID CurrentFocusScopeId; // Value for currently appending items == g.FocusScopeStack.back(). Not to be mistaken with g.NavFocusScopeId.
ImGuiItemFlags CurrentItemFlags; // == g.ItemFlagsStack.back() ImGuiItemFlags CurrentItemFlags; // Value for currently appending items == g.ItemFlagsStack.back()
ImGuiID DebugLocateId; // Storage for DebugLocateItemOnHover() feature: this is read by ItemAdd() so we keep it in a hot/cached location ImGuiID DebugLocateId; // Storage for DebugLocateItemOnHover() feature: this is read by ItemAdd() so we keep it in a hot/cached location
ImGuiNextItemData NextItemData; // Storage for SetNextItem** functions ImGuiNextItemData NextItemData; // Storage for SetNextItem** functions
ImGuiLastItemData LastItemData; // Storage for last submitted item (setup by ItemAdd) ImGuiLastItemData LastItemData; // Storage for last submitted item (setup by ItemAdd)
@@ -2144,17 +2210,16 @@ struct ImGuiContext
bool DebugShowGroupRects; bool DebugShowGroupRects;
// Shared stacks // Shared stacks
ImVector<ImGuiColorMod> ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin() ImGuiCol DebugFlashStyleColorIdx; // (Keep close to ColorStack to share cache line)
ImVector<ImGuiStyleMod> StyleVarStack; // Stack for PushStyleVar()/PopStyleVar() - inherited by Begin() ImVector<ImGuiColorMod> ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin()
ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont() - inherited by Begin() ImVector<ImGuiStyleMod> StyleVarStack; // Stack for PushStyleVar()/PopStyleVar() - inherited by Begin()
ImVector<ImGuiID> FocusScopeStack; // Stack for PushFocusScope()/PopFocusScope() - inherited by BeginChild(), pushed into by Begin() ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont() - inherited by Begin()
ImVector<ImGuiItemFlags> ItemFlagsStack; // Stack for PushItemFlag()/PopItemFlag() - inherited by Begin() ImVector<ImGuiFocusScopeData> FocusScopeStack; // Stack for PushFocusScope()/PopFocusScope() - inherited by BeginChild(), pushed into by Begin()
ImVector<ImGuiGroupData> GroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin() ImVector<ImGuiItemFlags> ItemFlagsStack; // Stack for PushItemFlag()/PopItemFlag() - inherited by Begin()
ImVector<ImGuiPopupData> OpenPopupStack; // Which popups are open (persistent) ImVector<ImGuiGroupData> GroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin()
ImVector<ImGuiPopupData> BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame) ImVector<ImGuiPopupData> OpenPopupStack; // Which popups are open (persistent)
ImVector<ImGuiNavTreeNodeData> NavTreeNodeStack; // Stack for TreeNode() when a NavLeft requested is emitted. ImVector<ImGuiPopupData> BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame)
ImVector<ImGuiNavTreeNodeData> NavTreeNodeStack; // Stack for TreeNode() when a NavLeft requested is emitted.
int BeginMenuCount;
// Viewports // Viewports
ImVector<ImGuiViewportP*> Viewports; // Active viewports (always 1+, and generally 1 unless multi-viewports are enabled). Each viewports hold their copy of ImDrawData. ImVector<ImGuiViewportP*> Viewports; // Active viewports (always 1+, and generally 1 unless multi-viewports are enabled). Each viewports hold their copy of ImDrawData.
@@ -2164,6 +2229,7 @@ struct ImGuiContext
ImGuiViewportP* MouseLastHoveredViewport; // Last known viewport that was hovered by mouse (even if we are not hovering any viewport any more) + honoring the _NoInputs flag. ImGuiViewportP* MouseLastHoveredViewport; // Last known viewport that was hovered by mouse (even if we are not hovering any viewport any more) + honoring the _NoInputs flag.
ImGuiID PlatformLastFocusedViewportId; ImGuiID PlatformLastFocusedViewportId;
ImGuiPlatformMonitor FallbackMonitor; // Virtual monitor used as fallback if backend doesn't provide monitor information. ImGuiPlatformMonitor FallbackMonitor; // Virtual monitor used as fallback if backend doesn't provide monitor information.
ImRect PlatformMonitorsFullWorkRect; // Bounding box of all platform monitors
int ViewportCreatedCount; // Unique sequential creation counter (mostly for testing/debugging) int ViewportCreatedCount; // Unique sequential creation counter (mostly for testing/debugging)
int PlatformWindowsCreatedCount; // Unique sequential creation counter (mostly for testing/debugging) int PlatformWindowsCreatedCount; // Unique sequential creation counter (mostly for testing/debugging)
int ViewportFocusedStampCount; // Every time the front-most window changes, we stamp its viewport with an incrementing counter int ViewportFocusedStampCount; // Every time the front-most window changes, we stamp its viewport with an incrementing counter
@@ -2171,11 +2237,14 @@ struct ImGuiContext
// Gamepad/keyboard Navigation // Gamepad/keyboard Navigation
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow' ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow'
ImGuiID NavId; // Focused item for navigation ImGuiID NavId; // Focused item for navigation
ImGuiID NavFocusScopeId; // Identify a selection scope (selection code often wants to "clear other items" when landing on an item of the selection set) ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope)
ImVector<ImGuiFocusScopeData> NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain.
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem() ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem()
ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0 ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0
ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat) ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat)
ImGuiActivateFlags NavActivateFlags; ImGuiActivateFlags NavActivateFlags;
ImGuiID NavHighlightActivatedId;
float NavHighlightActivatedTimer;
ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest). ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest).
ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest). ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest).
ImGuiKeyChord NavJustMovedToKeyMods; ImGuiKeyChord NavJustMovedToKeyMods;
@@ -2222,6 +2291,7 @@ struct ImGuiContext
float NavWindowingTimer; float NavWindowingTimer;
float NavWindowingHighlightAlpha; float NavWindowingHighlightAlpha;
bool NavWindowingToggleLayer; bool NavWindowingToggleLayer;
ImGuiKey NavWindowingToggleKey;
ImVec2 NavWindowingAccumDeltaPos; ImVec2 NavWindowingAccumDeltaPos;
ImVec2 NavWindowingAccumDeltaSize; ImVec2 NavWindowingAccumDeltaSize;
@@ -2237,6 +2307,7 @@ struct ImGuiContext
int DragDropMouseButton; int DragDropMouseButton;
ImGuiPayload DragDropPayload; ImGuiPayload DragDropPayload;
ImRect DragDropTargetRect; // Store rectangle of current target candidate (we favor small targets when overlapping) ImRect DragDropTargetRect; // Store rectangle of current target candidate (we favor small targets when overlapping)
ImRect DragDropTargetClipRect; // Store ClipRect at the time of item's drawing
ImGuiID DragDropTargetId; ImGuiID DragDropTargetId;
ImGuiDragDropFlags DragDropAcceptFlags; ImGuiDragDropFlags DragDropAcceptFlags;
float DragDropAcceptIdCurrRectSurface; // Target item surface (we resolve overlapping targets by prioritizing the smaller surface) float DragDropAcceptIdCurrRectSurface; // Target item surface (we resolve overlapping targets by prioritizing the smaller surface)
@@ -2253,6 +2324,7 @@ struct ImGuiContext
// Tables // Tables
ImGuiTable* CurrentTable; ImGuiTable* CurrentTable;
ImGuiID DebugBreakInTable; // Set to break in BeginTable() call.
int TablesTempDataStacked; // Temporary table data size (because we leave previous instances undestructed, we generally don't use TablesTempData.Size) int TablesTempDataStacked; // Temporary table data size (because we leave previous instances undestructed, we generally don't use TablesTempData.Size)
ImVector<ImGuiTableTempData> TablesTempData; // Temporary table data (buffers reused/shared across instances, support nesting) ImVector<ImGuiTableTempData> TablesTempData; // Temporary table data (buffers reused/shared across instances, support nesting)
ImPool<ImGuiTable> Tables; // Persistent table data ImPool<ImGuiTable> Tables; // Persistent table data
@@ -2283,6 +2355,8 @@ struct ImGuiContext
ImGuiInputTextDeactivatedState InputTextDeactivatedState; ImGuiInputTextDeactivatedState InputTextDeactivatedState;
ImFont InputTextPasswordFont; ImFont InputTextPasswordFont;
ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc.
int BeginMenuDepth;
int BeginComboDepth;
ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
ImGuiID ColorEditCurrentID; // Set temporarily while inside of the parent-most ColorEdit4/ColorPicker4 (because they call each others). ImGuiID ColorEditCurrentID; // Set temporarily while inside of the parent-most ColorEdit4/ColorPicker4 (because they call each others).
ImGuiID ColorEditSavedID; // ID we are saving/restoring HS for ImGuiID ColorEditSavedID; // ID we are saving/restoring HS for
@@ -2345,15 +2419,21 @@ struct ImGuiContext
int LogDepthToExpandDefault; // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call. int LogDepthToExpandDefault; // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call.
// Debug Tools // Debug Tools
// (some of the highly frequently used data are interleaved in other structures above: DebugBreakXXX fields, DebugHookIdInfo, DebugLocateId etc.)
ImGuiDebugLogFlags DebugLogFlags; ImGuiDebugLogFlags DebugLogFlags;
ImGuiTextBuffer DebugLogBuf; ImGuiTextBuffer DebugLogBuf;
ImGuiTextIndex DebugLogIndex; ImGuiTextIndex DebugLogIndex;
ImU8 DebugLogClipperAutoDisableFrames; ImGuiDebugLogFlags DebugLogAutoDisableFlags;
ImU8 DebugLogAutoDisableFrames;
ImU8 DebugLocateFrames; // For DebugLocateItemOnHover(). This is used together with DebugLocateId which is in a hot/cached spot above. ImU8 DebugLocateFrames; // For DebugLocateItemOnHover(). This is used together with DebugLocateId which is in a hot/cached spot above.
bool DebugBreakInLocateId; // Debug break in ItemAdd() call for g.DebugLocateId.
ImGuiKeyChord DebugBreakKeyChord; // = ImGuiKey_Pause
ImS8 DebugBeginReturnValueCullDepth; // Cycle between 0..9 then wrap around. ImS8 DebugBeginReturnValueCullDepth; // Cycle between 0..9 then wrap around.
bool DebugItemPickerActive; // Item picker is active (started with DebugStartItemPicker()) bool DebugItemPickerActive; // Item picker is active (started with DebugStartItemPicker())
ImU8 DebugItemPickerMouseButton; ImU8 DebugItemPickerMouseButton;
ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this ID ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this ID
float DebugFlashStyleColorTime;
ImVec4 DebugFlashStyleColorBackup;
ImGuiMetricsConfig DebugMetricsConfig; ImGuiMetricsConfig DebugMetricsConfig;
ImGuiIDStackTool DebugIDStackTool; ImGuiIDStackTool DebugIDStackTool;
ImGuiDebugAllocInfo DebugAllocInfo; ImGuiDebugAllocInfo DebugAllocInfo;
@@ -2368,6 +2448,7 @@ struct ImGuiContext
int WantCaptureKeyboardNextFrame; // " int WantCaptureKeyboardNextFrame; // "
int WantTextInputNextFrame; int WantTextInputNextFrame;
ImVector<char> TempBuffer; // Temporary text buffer ImVector<char> TempBuffer; // Temporary text buffer
char TempKeychordName[64];
ImGuiContext(ImFontAtlas* shared_font_atlas) ImGuiContext(ImFontAtlas* shared_font_atlas)
{ {
@@ -2414,6 +2495,7 @@ struct ImGuiContext
ActiveIdHasBeenPressedBefore = false; ActiveIdHasBeenPressedBefore = false;
ActiveIdHasBeenEditedBefore = false; ActiveIdHasBeenEditedBefore = false;
ActiveIdHasBeenEditedThisFrame = false; ActiveIdHasBeenEditedThisFrame = false;
ActiveIdFromShortcut = false;
ActiveIdClickOffset = ImVec2(-1, -1); ActiveIdClickOffset = ImVec2(-1, -1);
ActiveIdWindow = NULL; ActiveIdWindow = NULL;
ActiveIdSource = ImGuiInputSource_None; ActiveIdSource = ImGuiInputSource_None;
@@ -2425,6 +2507,8 @@ struct ImGuiContext
LastActiveId = 0; LastActiveId = 0;
LastActiveIdTimer = 0.0f; LastActiveIdTimer = 0.0f;
LastKeyboardKeyPressTime = LastKeyModsChangeTime = LastKeyModsChangeFromNoneTime = -1.0;
ActiveIdUsingNavDirMask = 0x00; ActiveIdUsingNavDirMask = 0x00;
ActiveIdUsingAllKeyboardKeys = false; ActiveIdUsingAllKeyboardKeys = false;
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
@@ -2434,7 +2518,6 @@ struct ImGuiContext
CurrentFocusScopeId = 0; CurrentFocusScopeId = 0;
CurrentItemFlags = ImGuiItemFlags_None; CurrentItemFlags = ImGuiItemFlags_None;
DebugShowGroupRects = false; DebugShowGroupRects = false;
BeginMenuCount = 0;
CurrentDpiScale = 0.0f; CurrentDpiScale = 0.0f;
CurrentViewport = NULL; CurrentViewport = NULL;
@@ -2447,6 +2530,8 @@ struct ImGuiContext
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0; NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0; NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None; NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
NavHighlightActivatedId = 0;
NavHighlightActivatedTimer = 0.0f;
NavJustMovedToKeyMods = ImGuiMod_None; NavJustMovedToKeyMods = ImGuiMod_None;
NavInputSource = ImGuiInputSource_Keyboard; NavInputSource = ImGuiInputSource_Keyboard;
NavLayer = ImGuiNavLayer_Main; NavLayer = ImGuiNavLayer_Main;
@@ -2474,6 +2559,7 @@ struct ImGuiContext
NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL; NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL;
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f; NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
NavWindowingToggleLayer = false; NavWindowingToggleLayer = false;
NavWindowingToggleKey = ImGuiKey_None;
DimBgRatio = 0.0f; DimBgRatio = 0.0f;
@@ -2502,6 +2588,7 @@ struct ImGuiContext
MouseStationaryTimer = 0.0f; MouseStationaryTimer = 0.0f;
TempInputId = 0; TempInputId = 0;
BeginMenuDepth = BeginComboDepth = 0;
ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_; ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
ColorEditCurrentID = ColorEditSavedID = 0; ColorEditCurrentID = ColorEditSavedID = 0;
ColorEditSavedHue = ColorEditSavedSat = 0.0f; ColorEditSavedHue = ColorEditSavedSat = 0.0f;
@@ -2542,18 +2629,29 @@ struct ImGuiContext
DebugLogFlags = ImGuiDebugLogFlags_OutputToTTY; DebugLogFlags = ImGuiDebugLogFlags_OutputToTTY;
DebugLocateId = 0; DebugLocateId = 0;
DebugLogClipperAutoDisableFrames = 0; DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None;
DebugLogAutoDisableFrames = 0;
DebugLocateFrames = 0; DebugLocateFrames = 0;
DebugBeginReturnValueCullDepth = -1; DebugBeginReturnValueCullDepth = -1;
DebugItemPickerActive = false; DebugItemPickerActive = false;
DebugItemPickerMouseButton = ImGuiMouseButton_Left; DebugItemPickerMouseButton = ImGuiMouseButton_Left;
DebugItemPickerBreakId = 0; DebugItemPickerBreakId = 0;
DebugFlashStyleColorTime = 0.0f;
DebugFlashStyleColorIdx = ImGuiCol_COUNT;
DebugHoveredDockNode = NULL; DebugHoveredDockNode = NULL;
// Same as DebugBreakClearData(). Those fields are scattered in their respective subsystem to stay in hot-data locations
DebugBreakInWindow = 0;
DebugBreakInTable = 0;
DebugBreakInLocateId = false;
DebugBreakKeyChord = ImGuiKey_Pause;
DebugBreakInShortcutRouting = ImGuiKey_None;
memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame)); memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));
FramerateSecPerFrameIdx = FramerateSecPerFrameCount = 0; FramerateSecPerFrameIdx = FramerateSecPerFrameCount = 0;
FramerateSecPerFrameAccum = 0.0f; FramerateSecPerFrameAccum = 0.0f;
WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1; WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1;
memset(TempKeychordName, 0, sizeof(TempKeychordName));
} }
}; };
@@ -2603,6 +2701,7 @@ struct IMGUI_API ImGuiWindowTempData
int CurrentTableIdx; // Current table index (into g.Tables) int CurrentTableIdx; // Current table index (into g.Tables)
ImGuiLayoutType LayoutType; ImGuiLayoutType LayoutType;
ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin() ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin()
ImU32 ModalDimBgColor;
// Local parameters stacks // Local parameters stacks
// We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings.
@@ -2716,6 +2815,7 @@ struct IMGUI_API ImGuiWindow
ImGuiWindow* RootWindowDockTree; // Point to ourself or first ancestor that is not a child window. Cross through dock nodes. ImGuiWindow* RootWindowDockTree; // Point to ourself or first ancestor that is not a child window. Cross through dock nodes.
ImGuiWindow* RootWindowForTitleBarHighlight; // Point to ourself or first ancestor which will display TitleBgActive color when this window is active. ImGuiWindow* RootWindowForTitleBarHighlight; // Point to ourself or first ancestor which will display TitleBgActive color when this window is active.
ImGuiWindow* RootWindowForNav; // Point to ourself or first ancestor which doesn't have the NavFlattened flag. ImGuiWindow* RootWindowForNav; // Point to ourself or first ancestor which doesn't have the NavFlattened flag.
ImGuiWindow* ParentWindowForFocusRoute; // Set to manual link a window to its logical parent so that Shortcut() chain are honoerd (e.g. Tool linked to Document)
ImGuiWindow* NavLastChildNavWindow; // When going to the menu bar, we remember the child window we came from. (This could probably be made implicit if we kept g.Windows sorted by last focused including child window.) ImGuiWindow* NavLastChildNavWindow; // When going to the menu bar, we remember the child window we came from. (This could probably be made implicit if we kept g.Windows sorted by last focused including child window.)
ImGuiID NavLastIds[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1) ImGuiID NavLastIds[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1)
@@ -3062,7 +3162,7 @@ struct IMGUI_API ImGuiTableTempData
{ {
int TableIndex; // Index in g.Tables.Buf[] pool int TableIndex; // Index in g.Tables.Buf[] pool
float LastTimeActive; // Last timestamp this structure was used float LastTimeActive; // Last timestamp this structure was used
float AngledheadersExtraWidth; // Used in EndTable() float AngledHeadersExtraWidth; // Used in EndTable()
ImVec2 UserOuterSize; // outer_size.x passed to BeginTable() ImVec2 UserOuterSize; // outer_size.x passed to BeginTable()
ImDrawListSplitter DrawSplitter; ImDrawListSplitter DrawSplitter;
@@ -3143,7 +3243,8 @@ namespace ImGui
IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0); IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0);
IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0); IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0);
IMGUI_API void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size); IMGUI_API void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size);
IMGUI_API void SetWindowHiddendAndSkipItemsForCurrentFrame(ImGuiWindow* window); IMGUI_API void SetWindowHiddenAndSkipItemsForCurrentFrame(ImGuiWindow* window);
inline void SetWindowParentWindowForFocusRoute(ImGuiWindow* window, ImGuiWindow* parent_window) { window->ParentWindowForFocusRoute = parent_window; } // You may also use SetNextWindowClass()'s FocusRouteParentWindowId field.
inline ImRect WindowRectAbsToRel(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x - off.x, r.Min.y - off.y, r.Max.x - off.x, r.Max.y - off.y); } inline ImRect WindowRectAbsToRel(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x - off.x, r.Min.y - off.y, r.Max.x - off.x, r.Max.y - off.y); }
inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); } inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); }
inline ImVec2 WindowPosRelToAbs(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x + off.x, p.y + off.y); } inline ImVec2 WindowPosRelToAbs(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x + off.x, p.y + off.y); }
@@ -3302,11 +3403,13 @@ namespace ImGui
IMGUI_API void NavMoveRequestCancel(); IMGUI_API void NavMoveRequestCancel();
IMGUI_API void NavMoveRequestApplyResult(); IMGUI_API void NavMoveRequestApplyResult();
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
IMGUI_API void NavHighlightActivated(ImGuiID id);
IMGUI_API void NavClearPreferredPosForAxis(ImGuiAxis axis); IMGUI_API void NavClearPreferredPosForAxis(ImGuiAxis axis);
IMGUI_API void NavRestoreHighlightAfterMove(); IMGUI_API void NavRestoreHighlightAfterMove();
IMGUI_API void NavUpdateCurrentWindowIsScrollPushableX(); IMGUI_API void NavUpdateCurrentWindowIsScrollPushableX();
IMGUI_API void SetNavWindow(ImGuiWindow* window); IMGUI_API void SetNavWindow(ImGuiWindow* window);
IMGUI_API void SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel); IMGUI_API void SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel);
IMGUI_API void SetNavFocusScope(ImGuiID focus_scope_id);
// Focus/Activation // Focus/Activation
// This should be part of a larger set of API: FocusItem(offset = -1), FocusItemByID(id), ActivateItem(offset = -1), ActivateItemByID(id) etc. which are // This should be part of a larger set of API: FocusItem(offset = -1), FocusItemByID(id), ActivateItem(offset = -1), ActivateItemByID(id) etc. which are
@@ -3323,7 +3426,8 @@ namespace ImGui
inline bool IsGamepadKey(ImGuiKey key) { return key >= ImGuiKey_Gamepad_BEGIN && key < ImGuiKey_Gamepad_END; } inline bool IsGamepadKey(ImGuiKey key) { return key >= ImGuiKey_Gamepad_BEGIN && key < ImGuiKey_Gamepad_END; }
inline bool IsMouseKey(ImGuiKey key) { return key >= ImGuiKey_Mouse_BEGIN && key < ImGuiKey_Mouse_END; } inline bool IsMouseKey(ImGuiKey key) { return key >= ImGuiKey_Mouse_BEGIN && key < ImGuiKey_Mouse_END; }
inline bool IsAliasKey(ImGuiKey key) { return key >= ImGuiKey_Aliases_BEGIN && key < ImGuiKey_Aliases_END; } inline bool IsAliasKey(ImGuiKey key) { return key >= ImGuiKey_Aliases_BEGIN && key < ImGuiKey_Aliases_END; }
inline ImGuiKeyChord ConvertShortcutMod(ImGuiKeyChord key_chord) { ImGuiContext& g = *GImGui; IM_ASSERT_PARANOID(key_chord & ImGuiMod_Shortcut); return (key_chord & ~ImGuiMod_Shortcut) | (g.IO.ConfigMacOSXBehaviors ? ImGuiMod_Super : ImGuiMod_Ctrl); } inline bool IsModKey(ImGuiKey key) { return key >= ImGuiKey_LeftCtrl && key <= ImGuiKey_RightSuper; }
ImGuiKeyChord FixupKeyChord(ImGuiContext* ctx, ImGuiKeyChord key_chord);
inline ImGuiKey ConvertSingleModFlagToKey(ImGuiContext* ctx, ImGuiKey key) inline ImGuiKey ConvertSingleModFlagToKey(ImGuiContext* ctx, ImGuiKey key)
{ {
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
@@ -3337,7 +3441,7 @@ namespace ImGui
IMGUI_API ImGuiKeyData* GetKeyData(ImGuiContext* ctx, ImGuiKey key); IMGUI_API ImGuiKeyData* GetKeyData(ImGuiContext* ctx, ImGuiKey key);
inline ImGuiKeyData* GetKeyData(ImGuiKey key) { ImGuiContext& g = *GImGui; return GetKeyData(&g, key); } inline ImGuiKeyData* GetKeyData(ImGuiKey key) { ImGuiContext& g = *GImGui; return GetKeyData(&g, key); }
IMGUI_API void GetKeyChordName(ImGuiKeyChord key_chord, char* out_buf, int out_buf_size); IMGUI_API const char* GetKeyChordName(ImGuiKeyChord key_chord);
inline ImGuiKey MouseButtonToKey(ImGuiMouseButton button) { IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT); return (ImGuiKey)(ImGuiKey_MouseLeft + button); } inline ImGuiKey MouseButtonToKey(ImGuiMouseButton button) { IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT); return (ImGuiKey)(ImGuiKey_MouseLeft + button); }
IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f); IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f);
IMGUI_API ImVec2 GetKeyMagnitude2d(ImGuiKey key_left, ImGuiKey key_right, ImGuiKey key_up, ImGuiKey key_down); IMGUI_API ImVec2 GetKeyMagnitude2d(ImGuiKey key_left, ImGuiKey key_right, ImGuiKey key_up, ImGuiKey key_down);
@@ -3394,8 +3498,9 @@ namespace ImGui
// - IsKeyChordPressed() compares mods + call IsKeyPressed() -> function has no side-effect. // - IsKeyChordPressed() compares mods + call IsKeyPressed() -> function has no side-effect.
// - Shortcut() submits a route then if currently can be routed calls IsKeyChordPressed() -> function has (desirable) side-effects. // - Shortcut() submits a route then if currently can be routed calls IsKeyChordPressed() -> function has (desirable) side-effects.
IMGUI_API bool IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags = 0); IMGUI_API bool IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags = 0);
IMGUI_API void SetNextItemShortcut(ImGuiKeyChord key_chord);
IMGUI_API bool Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id = 0, ImGuiInputFlags flags = 0); IMGUI_API bool Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id = 0, ImGuiInputFlags flags = 0);
IMGUI_API bool SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id = 0, ImGuiInputFlags flags = 0); IMGUI_API bool SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags = 0); // owner_id needs to be explicit and cannot be 0
IMGUI_API bool TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id); IMGUI_API bool TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id);
IMGUI_API ImGuiKeyRoutingData* GetShortcutRoutingData(ImGuiKeyChord key_chord); IMGUI_API ImGuiKeyRoutingData* GetShortcutRoutingData(ImGuiKeyChord key_chord);
@@ -3471,7 +3576,7 @@ namespace ImGui
IMGUI_API bool BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id); IMGUI_API bool BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id);
IMGUI_API void ClearDragDrop(); IMGUI_API void ClearDragDrop();
IMGUI_API bool IsDragDropPayloadBeingAccepted(); IMGUI_API bool IsDragDropPayloadBeingAccepted();
IMGUI_API void RenderDragDropTargetRect(const ImRect& bb); IMGUI_API void RenderDragDropTargetRect(const ImRect& bb, const ImRect& item_clip_rect);
// Typing-Select API // Typing-Select API
IMGUI_API ImGuiTypingSelectRequest* GetTypingSelectRequest(ImGuiTypingSelectFlags flags = ImGuiTypingSelectFlags_None); IMGUI_API ImGuiTypingSelectRequest* GetTypingSelectRequest(ImGuiTypingSelectFlags flags = ImGuiTypingSelectFlags_None);
@@ -3501,7 +3606,7 @@ namespace ImGui
IMGUI_API float TableGetHeaderAngledMaxLabelWidth(); IMGUI_API float TableGetHeaderAngledMaxLabelWidth();
IMGUI_API void TablePushBackgroundChannel(); IMGUI_API void TablePushBackgroundChannel();
IMGUI_API void TablePopBackgroundChannel(); IMGUI_API void TablePopBackgroundChannel();
IMGUI_API void TableAngledHeadersRowEx(float angle, float label_width = 0.0f); IMGUI_API void TableAngledHeadersRowEx(float angle, float max_label_width = 0.0f);
// Tables: Internals // Tables: Internals
inline ImGuiTable* GetCurrentTable() { ImGuiContext& g = *GImGui; return g.CurrentTable; } inline ImGuiTable* GetCurrentTable() { ImGuiContext& g = *GImGui; return g.CurrentTable; }
@@ -3581,7 +3686,7 @@ namespace ImGui
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f);
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f); IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0); IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0);
IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_TypeDefault); // Navigation highlight IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_None); // Navigation highlight
IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text.
IMGUI_API void RenderMouseCursor(ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow); IMGUI_API void RenderMouseCursor(ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow);
@@ -3685,7 +3790,9 @@ namespace ImGui
IMGUI_API void DebugLocateItem(ImGuiID target_id); // Call sparingly: only 1 at the same time! IMGUI_API void DebugLocateItem(ImGuiID target_id); // Call sparingly: only 1 at the same time!
IMGUI_API void DebugLocateItemOnHover(ImGuiID target_id); // Only call on reaction to a mouse Hover: because only 1 at the same time! IMGUI_API void DebugLocateItemOnHover(ImGuiID target_id); // Only call on reaction to a mouse Hover: because only 1 at the same time!
IMGUI_API void DebugLocateItemResolveWithLastItem(); IMGUI_API void DebugLocateItemResolveWithLastItem();
inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; } IMGUI_API void DebugBreakClearData();
IMGUI_API bool DebugBreakButton(const char* label, const char* description_of_location);
IMGUI_API void DebugBreakButtonTooltip(bool keyboard_only, const char* description_of_location);
IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas);
IMGUI_API void DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* data_id, const void* data_id_end); IMGUI_API void DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* data_id, const void* data_id_end);
IMGUI_API void DebugNodeColumns(ImGuiOldColumns* columns); IMGUI_API void DebugNodeColumns(ImGuiOldColumns* columns);
@@ -3713,13 +3820,12 @@ namespace ImGui
inline void SetItemUsingMouseWheel() { SetItemKeyOwner(ImGuiKey_MouseWheelY); } // Changed in 1.89 inline void SetItemUsingMouseWheel() { SetItemKeyOwner(ImGuiKey_MouseWheelY); } // Changed in 1.89
inline bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0) { return TreeNodeUpdateNextOpen(id, flags); } // Renamed in 1.89 inline bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0) { return TreeNodeUpdateNextOpen(id, flags); } // Renamed in 1.89
// Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets that used FocusableItemRegister(): // Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets which used FocusableItemRegister():
// (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool tab_focused = FocusableItemRegister(...)' // (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool tab_focused = FocusableItemRegister(...)'
// (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0' // (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0'
// (New) IMGUI_VERSION_NUM >= 18413: using 'ItemAdd(..., ImGuiItemFlags_Inputable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_FocusedTabbing) != 0 || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput))' (WIP) // (New) IMGUI_VERSION_NUM >= 18413: using 'ItemAdd(..., ImGuiItemFlags_Inputable)' and 'bool tab_focused = (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput))'
// Widget code are simplified as there's no need to call FocusableItemUnregister() while managing the transition from regular widget to TempInputText() //inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) // -> pass ImGuiItemAddFlags_Inputable flag to ItemAdd()
inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) { IM_ASSERT(0); IM_UNUSED(window); IM_UNUSED(id); return false; } // -> pass ImGuiItemAddFlags_Inputable flag to ItemAdd() //inline void FocusableItemUnregister(ImGuiWindow* window) // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem
inline void FocusableItemUnregister(ImGuiWindow* window) { IM_ASSERT(0); IM_UNUSED(window); } // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem
#endif #endif
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { IM_ASSERT(IsNamedKey(key)); return IsKeyPressed(key, repeat); } // Removed in 1.87: Mapping from named key is always identity! inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { IM_ASSERT(IsNamedKey(key)); return IsKeyPressed(key, repeat); } // Removed in 1.87: Mapping from named key is always identity!

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.90.0 // dear imgui, v1.90.4
// (tables and columns code) // (tables and columns code)
/* /*
@@ -329,6 +329,10 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
return false; return false;
} }
// [DEBUG] Debug break requested by user
if (g.DebugBreakInTable == id)
IM_DEBUG_BREAK();
// Acquire storage for the table // Acquire storage for the table
ImGuiTable* table = g.Tables.GetOrAddByKey(id); ImGuiTable* table = g.Tables.GetOrAddByKey(id);
const ImGuiTableFlags table_last_flags = table->Flags; const ImGuiTableFlags table_last_flags = table->Flags;
@@ -494,7 +498,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->DeclColumnsCount = table->AngledHeadersCount = 0; table->DeclColumnsCount = table->AngledHeadersCount = 0;
if (previous_frame_active + 1 < g.FrameCount) if (previous_frame_active + 1 < g.FrameCount)
table->IsActiveIdInTable = false; table->IsActiveIdInTable = false;
temp_data->AngledheadersExtraWidth = 0.0f; temp_data->AngledHeadersExtraWidth = 0.0f;
// Using opaque colors facilitate overlapping lines of the grid, otherwise we'd need to improve TableDrawBorders() // Using opaque colors facilitate overlapping lines of the grid, otherwise we'd need to improve TableDrawBorders()
table->BorderColorStrong = GetColorU32(ImGuiCol_TableBorderStrong); table->BorderColorStrong = GetColorU32(ImGuiCol_TableBorderStrong);
@@ -1340,7 +1344,7 @@ void ImGui::EndTable()
max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].WorkMaxX + table->CellPaddingX + table->OuterPaddingX - outer_padding_for_border); max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].WorkMaxX + table->CellPaddingX + table->OuterPaddingX - outer_padding_for_border);
if (table->ResizedColumn != -1) if (table->ResizedColumn != -1)
max_pos_x = ImMax(max_pos_x, table->ResizeLockMinContentsX2); 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 // Pop clipping rect
@@ -1458,7 +1462,7 @@ void ImGui::EndTable()
} }
else if (temp_data->UserOuterSize.x <= 0.0f) 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); 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.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)); outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth));
} }
@@ -1563,6 +1567,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo
} }
// Store name (append with zero-terminator in contiguous buffer) // 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; column->NameOffset = -1;
if (label != NULL && label[0] != 0) if (label != NULL && label[0] != 0)
{ {
@@ -2150,6 +2155,8 @@ void ImGui::TableEndCell(ImGuiTable* table)
// - TableSetColumnWidthAutoAll() [Internal] // - TableSetColumnWidthAutoAll() [Internal]
// - TableUpdateColumnsWeightFromWidth() [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. // 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) float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n)
@@ -2923,6 +2930,7 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table)
// [SECTION] Tables: Headers // [SECTION] Tables: Headers
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// - TableGetHeaderRowHeight() [Internal] // - TableGetHeaderRowHeight() [Internal]
// - TableGetHeaderAngledMaxLabelWidth() [Internal]
// - TableHeadersRow() // - TableHeadersRow()
// - TableHeader() // - TableHeader()
// - TableAngledHeadersRow() // - TableAngledHeadersRow()
@@ -2954,7 +2962,7 @@ float ImGui::TableGetHeaderAngledMaxLabelWidth()
if (IM_BITARRAY_TESTBIT(table->EnabledMaskByIndex, column_n)) if (IM_BITARRAY_TESTBIT(table->EnabledMaskByIndex, column_n))
if (table->Columns[column_n].Flags & ImGuiTableColumnFlags_AngledHeader) if (table->Columns[column_n].Flags & ImGuiTableColumnFlags_AngledHeader)
width = ImMax(width, CalcTextSize(TableGetColumnName(table, column_n), NULL, true).x); 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(). // [Public] This is a helper to output TableHeader() calls based on the column names declared in TableSetupColumn().
@@ -3078,7 +3086,7 @@ void ImGui::TableHeader(const char* label)
if ((table->RowFlags & ImGuiTableRowFlags_Headers) == 0) if ((table->RowFlags & ImGuiTableRowFlags_Headers) == 0)
TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_TableHeaderBg), table->CurrentColumn); TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_TableHeaderBg), table->CurrentColumn);
} }
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_Compact | ImGuiNavHighlightFlags_NoRounding);
if (held) if (held)
table->HeldHeaderColumn = (ImGuiTableColumnIdx)column_n; table->HeldHeaderColumn = (ImGuiTableColumnIdx)column_n;
window->DC.CursorPos.y -= g.Style.ItemSpacing.y * 0.5f; window->DC.CursorPos.y -= g.Style.ItemSpacing.y * 0.5f;
@@ -3176,25 +3184,25 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width)
// Calculate our base metrics and set angled headers data _before_ the first call to TableNextRow() // 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. // 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 header_height = g.FontSize + g.Style.CellPadding.x * 2.0f;
const float row_height = ImFabs(ImRotate(ImVec2(max_label_width, flip_label ? +header_height : -header_height), cos_a, sin_a).y); 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);
table->AngledHeadersHeight = row_height; table->AngledHeadersHeight = row_height;
table->AngledHeadersSlope = (sin_a != 0.0f) ? (cos_a / sin_a) : 0.0f; 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 // Declare row, override and draw our own background
TableNextRow(ImGuiTableRowFlags_Headers, row_height); TableNextRow(ImGuiTableRowFlags_Headers, row_height);
TableNextColumn(); 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); table->DrawSplitter->SetCurrentChannel(draw_list, TABLE_DRAW_CHANNEL_BG0);
float clip_rect_min_x = table->BgClipRect.Min.x; float clip_rect_min_x = table->BgClipRect.Min.x;
if (table->FreezeColumnsCount > 0) if (table->FreezeColumnsCount > 0)
clip_rect_min_x = ImMax(clip_rect_min_x, table->Columns[table->FreezeColumnsCount - 1].MaxX); clip_rect_min_x = ImMax(clip_rect_min_x, table->Columns[table->FreezeColumnsCount - 1].MaxX);
TableSetBgColor(ImGuiTableBgTarget_RowBg0, 0); // Cancel TableSetBgColor(ImGuiTableBgTarget_RowBg0, 0); // Cancel
PushClipRect(table->BgClipRect.Min, table->BgClipRect.Max, false); // Span all columns 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 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"); const ImGuiID row_id = GetID("##AngledHeaders");
ButtonBehavior(row_r, row_id, NULL, NULL); ButtonBehavior(row_r, row_id, NULL, NULL);
KeepAliveID(row_id); KeepAliveID(row_id);
@@ -3205,7 +3213,9 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width)
if (table_instance->HoveredRowLast == 0 && table->HoveredColumnBorder == -1 && (g.ActiveId == 0 || g.ActiveId == row_id || (table->IsActiveIdInTable || g.DragDropActive))) if (table_instance->HoveredRowLast == 0 && table->HoveredColumnBorder == -1 && (g.ActiveId == 0 || g.ActiveId == row_id || (table->IsActiveIdInTable || g.DragDropActive)))
highlight_column_n = table->HoveredColumnBody; highlight_column_n = table->HoveredColumnBody;
// Draw background and labels in first pass, then all borders.
float max_x = 0.0f; float max_x = 0.0f;
ImVec2 padding = g.Style.CellPadding; // We will always use swapped component
for (int pass = 0; pass < 2; pass++) 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 < table->ColumnsCount; order_n++)
{ {
@@ -3227,25 +3237,45 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width)
draw_list->AddQuadFilled(bg_shape[0], bg_shape[1], bg_shape[2], bg_shape[3], GetColorU32(ImGuiCol_TableHeaderBg)); draw_list->AddQuadFilled(bg_shape[0], bg_shape[1], bg_shape[2], bg_shape[3], GetColorU32(ImGuiCol_TableHeaderBg));
if (column_n == highlight_column_n) 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->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);
max_x = ImMax(max_x, bg_shape[3].x); 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) // Draw label
// FIXME: May be worth tidying up all those operations to make them easier to understand. // - 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 char* label_name = TableGetColumnName(table, column_n);
const float clip_width = max_label_width - (sin_a * table->RowCellPaddingY); const char* label_name_end = FindRenderedTextEnd(label_name);
ImRect label_r(window->ClipRect.Min, window->ClipRect.Min + ImVec2(clip_width + (flip_label ? 0.0f : table->CellPaddingX), header_height + table->RowCellPaddingY)); const float line_off_step_x = g.FontSize / -sin_a;
ImVec2 label_size = CalcTextSize(label_name, NULL, true); float line_off_curr_x = 0.0f;
ImVec2 label_off = ImVec2(flip_label ? ImMax(0.0f, max_label_width - label_size.x - table->CellPaddingX) : table->CellPaddingX, table->RowCellPaddingY); while (label_name < label_name_end)
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); const char* label_name_eol = strchr(label_name, '\n');
//if (g.IO.KeyShift) { draw_list->AddRect(label_r.Min, label_r.Max, IM_COL32(0, 255, 0, 255), 0.0f, 0, 2.0f); } if (label_name_eol == NULL)
int vtx_idx_end = draw_list->_VtxCurrentIdx; label_name_eol = label_name_end;
// Rotate and offset label // FIXME: Individual line clipping for right-most column is broken for negative angles.
ImVec2 pivot_in = label_r.GetBL(); ImVec2 label_size = CalcTextSize(label_name, label_name_eol);
ImVec2 pivot_out = ImVec2(column->WorkMinX, row_r.Max.y) + (flip_label ? (unit_right * clip_width) : ImVec2(header_height, 0.0f)); float clip_width = max_label_width - padding.y; // Using padding.y*2.0f would be symetrical but hide more text.
ShadeVertsTransformPos(draw_list, vtx_idx_begin, vtx_idx_end, pivot_in, label_cos_a, label_sin_a, pivot_out); // Rotate and offset 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;
RenderTextEllipsis(draw_list, clip_r.Min, clip_r.Max, clip_r.Max.x, clip_r.Max.x, label_name, label_name_eol, &label_size);
int vtx_idx_end = draw_list->_VtxCurrentIdx;
// Rotate and offset label
ImVec2 pivot_in = ImVec2(window->ClipRect.Min.x, window->ClipRect.Min.y + label_size.y);
ImVec2 pivot_out = ImVec2(column->WorkMinX, row_r.Max.y);
line_off_curr_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, 2.0f); ShadeVertsTransformPos(fg_dl, vtx_idx_begin, fg_dl->_VtxCurrentIdx, pivot_in, label_cos_a, label_sin_a, pivot_out); }
// Register header width
column->ContentMaxXHeadersUsed = column->ContentMaxXHeadersIdeal = column->WorkMinX + ImCeil(line_off_curr_x);
label_name = label_name_eol + 1;
}
} }
if (pass == 1) if (pass == 1)
{ {
@@ -3255,7 +3285,7 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width)
} }
PopClipRect(); PopClipRect();
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 +3832,8 @@ static const char* DebugNodeTableGetSizingPolicyDesc(ImGuiTableFlags sizing_poli
void ImGui::DebugNodeTable(ImGuiTable* table) 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)); } 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*"); bool open = TreeNode(table, "Table 0x%08X (%d columns, in '%s')%s", table->ID, table->ColumnsCount, table->OuterWindow->Name, is_active ? "" : " *Inactive*");
if (!is_active) { PopStyleColor(); } if (!is_active) { PopStyleColor(); }
@@ -3814,6 +3845,13 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
return; return;
if (table->InstanceCurrent > 0) if (table->InstanceCurrent > 0)
Text("** %d instances of same table! Some data below will refer to last instance.", table->InstanceCurrent + 1); 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"); 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("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)" : ""); BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : "");

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.90.0 // dear imgui, v1.90.4
// (widgets code) // (widgets code)
/* /*
@@ -477,6 +477,9 @@ void ImGui::BulletTextV(const char* fmt, va_list args)
// Frame N + RepeatDelay + RepeatRate*N true true - true // Frame N + RepeatDelay + RepeatRate*N true true - true
//------------------------------------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------------------------------------
// FIXME: For refactor we could output flags, incl mouse hovered vs nav keyboard vs nav triggered etc.
// And better standardize how widgets use 'GetColor32((held && hovered) ? ... : hovered ? ...)' vs 'GetColor32(held ? ... : hovered ? ...);'
// For mouse feedback we typically prefer the 'held && hovered' test, but for nav feedback not always. Outputting hovered=true on Activation may be misleading.
bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags) bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@@ -597,9 +600,9 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
g.NavDisableHighlight = true; g.NavDisableHighlight = true;
} }
// Gamepad/Keyboard navigation // Gamepad/Keyboard handling
// We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse. // We report navigated and navigation-activated items as hovered but we don't set g.HoveredId to not interfere with mouse.
if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover && (g.ActiveId == 0 || g.ActiveId == id || g.ActiveId == window->MoveId)) if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover)
if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus)) if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus))
hovered = true; hovered = true;
if (g.NavActivateDownId == id) if (g.NavActivateDownId == id)
@@ -621,8 +624,10 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
pressed = true; pressed = true;
SetActiveID(id, window); SetActiveID(id, window);
g.ActiveIdSource = g.NavInputSource; g.ActiveIdSource = g.NavInputSource;
if (!(flags & ImGuiButtonFlags_NoNavFocus)) if (!(flags & ImGuiButtonFlags_NoNavFocus) && !(g.NavActivateFlags & ImGuiActivateFlags_FromShortcut))
SetFocusID(id, window); SetFocusID(id, window);
if (g.NavActivateFlags & ImGuiActivateFlags_FromShortcut)
g.ActiveIdFromShortcut = true;
} }
} }
@@ -666,13 +671,19 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad) else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
{ {
// When activated using Nav, we hold on the ActiveID until activation button is released // When activated using Nav, we hold on the ActiveID until activation button is released
if (g.NavActivateDownId != id) if (g.NavActivateDownId == id)
held = true; // hovered == true not true as we are already likely hovered on direct activation.
else
ClearActiveID(); ClearActiveID();
} }
if (pressed) if (pressed)
g.ActiveIdHasBeenPressedBefore = true; g.ActiveIdHasBeenPressedBefore = true;
} }
// Activation highlight (this may be a remote activation)
if (g.NavHighlightActivatedId == id)
hovered = true;
if (out_hovered) *out_hovered = hovered; if (out_hovered) *out_hovered = hovered;
if (out_held) *out_held = held; if (out_held) *out_held = held;
@@ -972,7 +983,6 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
// Click position in scrollbar normalized space (0.0f->1.0f) // Click position in scrollbar normalized space (0.0f->1.0f)
const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v); const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v);
SetHoveredID(id);
bool seek_absolute = false; bool seek_absolute = false;
if (g.ActiveIdIsJustActivated) if (g.ActiveIdIsJustActivated)
@@ -1013,28 +1023,25 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
return held; return held;
} }
void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) // - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
// - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above.
void ImGui::Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems) if (window->SkipItems)
return; return;
ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); const float border_size = (border_col.w > 0.0f) ? 1.0f : 0.0f;
if (border_col.w > 0.0f) const ImVec2 padding(border_size, border_size);
bb.Max += ImVec2(2, 2); const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + image_size + padding * 2.0f);
ItemSize(bb); ItemSize(bb);
if (!ItemAdd(bb, 0)) if (!ItemAdd(bb, 0))
return; return;
if (border_col.w > 0.0f) // Render
{ if (border_size > 0.0f)
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(border_col), 0.0f); window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(border_col), 0.0f, ImDrawFlags_None, border_size);
window->DrawList->AddImage(user_texture_id, bb.Min + ImVec2(1, 1), bb.Max - ImVec2(1, 1), uv0, uv1, GetColorU32(tint_col)); window->DrawList->AddImage(user_texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
}
else
{
window->DrawList->AddImage(user_texture_id, bb.Min, bb.Max, uv0, uv1, GetColorU32(tint_col));
}
} }
// ImageButton() is flawed as 'id' is always derived from 'texture_id' (see #2464 #1390) // ImageButton() is flawed as 'id' is always derived from 'texture_id' (see #2464 #1390)
@@ -1685,7 +1692,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
const ImGuiID id = window->GetID(label); const ImGuiID id = window->GetID(label);
IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together
if (flags & ImGuiComboFlags_WidthFitPreview) if (flags & ImGuiComboFlags_WidthFitPreview)
IM_ASSERT((flags & (ImGuiComboFlags_NoPreview | ImGuiComboFlags_CustomPreview)) == 0); IM_ASSERT((flags & (ImGuiComboFlags_NoPreview | (ImGuiComboFlags)ImGuiComboFlags_CustomPreview)) == 0);
const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight(); const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImVec2 label_size = CalcTextSize(label, NULL, true);
@@ -1783,7 +1790,7 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags
// This is essentially a specialized version of BeginPopupEx() // This is essentially a specialized version of BeginPopupEx()
char name[16]; char name[16];
ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginComboDepth); // Recycle windows based on depth
// Set position given a custom constraint (peak into expected window size so we can position it) // Set position given a custom constraint (peak into expected window size so we can position it)
// FIXME: This might be easier to express with an hypothetical SetNextWindowPosConstraints() function? // FIXME: This might be easier to express with an hypothetical SetNextWindowPosConstraints() function?
@@ -1810,12 +1817,15 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags
IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above
return false; return false;
} }
g.BeginComboDepth++;
return true; return true;
} }
void ImGui::EndCombo() void ImGui::EndCombo()
{ {
ImGuiContext& g = *GImGui;
EndPopup(); EndPopup();
g.BeginComboDepth--;
} }
// Call directly after the BeginCombo/EndCombo block. The preview is designed to only host non-interactive elements // Call directly after the BeginCombo/EndCombo block. The preview is designed to only host non-interactive elements
@@ -1991,7 +2001,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*old_getter)(void*
// - DataTypeGetInfo() // - DataTypeGetInfo()
// - DataTypeFormatString() // - DataTypeFormatString()
// - DataTypeApplyOp() // - DataTypeApplyOp()
// - DataTypeApplyOpFromText() // - DataTypeApplyFromText()
// - DataTypeCompare() // - DataTypeCompare()
// - DataTypeClamp() // - DataTypeClamp()
// - GetMinimumStepAtDecimalPrecision // - GetMinimumStepAtDecimalPrecision
@@ -2438,14 +2448,13 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
if (!temp_input_is_active) if (!temp_input_is_active)
{ {
// Tabbing or CTRL-clicking on Drag turns it into an InputText // Tabbing or CTRL-clicking on Drag turns it into an InputText
const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
const bool clicked = hovered && IsMouseClicked(0, id); const bool clicked = hovered && IsMouseClicked(0, id);
const bool double_clicked = (hovered && g.IO.MouseClickedCount[0] == 2 && TestKeyOwner(ImGuiKey_MouseLeft, id)); const bool double_clicked = (hovered && g.IO.MouseClickedCount[0] == 2 && TestKeyOwner(ImGuiKey_MouseLeft, id));
const bool make_active = (input_requested_by_tabbing || clicked || double_clicked || g.NavActivateId == id); const bool make_active = (clicked || double_clicked || g.NavActivateId == id);
if (make_active && (clicked || double_clicked)) if (make_active && (clicked || double_clicked))
SetKeyOwner(ImGuiKey_MouseLeft, id); SetKeyOwner(ImGuiKey_MouseLeft, id);
if (make_active && temp_input_allowed) if (make_active && temp_input_allowed)
if (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || double_clicked || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput))) if ((clicked && g.IO.KeyCtrl) || double_clicked || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput)))
temp_input_is_active = true; temp_input_is_active = true;
// (Optional) simple click (without moving) turns Drag into an InputText // (Optional) simple click (without moving) turns Drag into an InputText
@@ -3030,13 +3039,12 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
if (!temp_input_is_active) if (!temp_input_is_active)
{ {
// Tabbing or CTRL-clicking on Slider turns it into an input box // Tabbing or CTRL-clicking on Slider turns it into an input box
const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
const bool clicked = hovered && IsMouseClicked(0, id); const bool clicked = hovered && IsMouseClicked(0, id);
const bool make_active = (input_requested_by_tabbing || clicked || g.NavActivateId == id); const bool make_active = (clicked || g.NavActivateId == id);
if (make_active && clicked) if (make_active && clicked)
SetKeyOwner(ImGuiKey_MouseLeft, id); SetKeyOwner(ImGuiKey_MouseLeft, id);
if (make_active && temp_input_allowed) if (make_active && temp_input_allowed)
if (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput))) if ((clicked && g.IO.KeyCtrl) || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput)))
temp_input_is_active = true; temp_input_is_active = true;
if (make_active && !temp_input_is_active) if (make_active && !temp_input_is_active)
@@ -3408,14 +3416,6 @@ bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char*
return value_changed; return value_changed;
} }
static inline ImGuiInputTextFlags InputScalar_DefaultCharsFilter(ImGuiDataType data_type, const char* format)
{
if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
return ImGuiInputTextFlags_CharsScientific;
const char format_last_char = format[0] ? format[strlen(format) - 1] : 0;
return (format_last_char == 'x' || format_last_char == 'X') ? ImGuiInputTextFlags_CharsHexadecimal : ImGuiInputTextFlags_CharsDecimal;
}
// Note that Drag/Slider functions are only forwarding the min/max values clamping values if the ImGuiSliderFlags_AlwaysClamp flag is set! // Note that Drag/Slider functions are only forwarding the min/max values clamping values if the ImGuiSliderFlags_AlwaysClamp flag is set!
// This is intended: this way we allow CTRL+Click manual input to set a value out of bounds, for maximum flexibility. // This is intended: this way we allow CTRL+Click manual input to set a value out of bounds, for maximum flexibility.
// However this may not be ideal for all uses, as some user code may break on out of bound values. // However this may not be ideal for all uses, as some user code may break on out of bound values.
@@ -3432,8 +3432,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format); DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format);
ImStrTrimBlanks(data_buf); ImStrTrimBlanks(data_buf);
ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoMarkEdited; ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited;
flags |= InputScalar_DefaultCharsFilter(data_type, format);
bool value_changed = false; bool value_changed = false;
if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags)) if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags))
@@ -3477,10 +3476,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
char buf[64]; char buf[64];
DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format); DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format);
// Testing ActiveId as a minor optimization as filtering is not needed until active flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
if (g.ActiveId == 0 && (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0)
flags |= InputScalar_DefaultCharsFilter(data_type, format);
flags |= ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
bool value_changed = false; bool value_changed = false;
if (p_step == NULL) if (p_step == NULL)
@@ -3574,7 +3570,6 @@ bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* p_dat
bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, const char* format, ImGuiInputTextFlags flags) bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, const char* format, ImGuiInputTextFlags flags)
{ {
flags |= ImGuiInputTextFlags_CharsScientific;
return InputScalar(label, ImGuiDataType_Float, (void*)v, (void*)(step > 0.0f ? &step : NULL), (void*)(step_fast > 0.0f ? &step_fast : NULL), format, flags); return InputScalar(label, ImGuiDataType_Float, (void*)v, (void*)(step > 0.0f ? &step : NULL), (void*)(step_fast > 0.0f ? &step_fast : NULL), format, flags);
} }
@@ -3617,7 +3612,6 @@ bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags)
bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags flags) bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags flags)
{ {
flags |= ImGuiInputTextFlags_CharsScientific;
return InputScalar(label, ImGuiDataType_Double, (void*)v, (void*)(step > 0.0 ? &step : NULL), (void*)(step_fast > 0.0 ? &step_fast : NULL), format, flags); return InputScalar(label, ImGuiDataType_Double, (void*)v, (void*)(step > 0.0 ? &step : NULL), (void*)(step_fast > 0.0 ? &step_fast : NULL), format, flags);
} }
@@ -3716,7 +3710,7 @@ namespace ImStb
static int STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj) { return obj->CurLenW; } static int STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj) { return obj->CurLenW; }
static ImWchar STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { IM_ASSERT(idx <= obj->CurLenW); return obj->TextW[idx]; } static ImWchar STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { IM_ASSERT(idx <= obj->CurLenW); return obj->TextW[idx]; }
static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { ImWchar c = obj->TextW[line_start_idx + char_idx]; if (c == '\n') return STB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance(c) * (g.FontSize / g.Font->FontSize); } static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { ImWchar c = obj->TextW[line_start_idx + char_idx]; if (c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance(c) * (g.FontSize / g.Font->FontSize); }
static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x200000 ? 0 : key; } static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x200000 ? 0 : key; }
static ImWchar STB_TEXTEDIT_NEWLINE = '\n'; static ImWchar STB_TEXTEDIT_NEWLINE = '\n';
static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx) static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
@@ -3834,13 +3828,13 @@ static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const Im
#define STB_TEXTEDIT_K_PGDOWN 0x20000F // keyboard input to move cursor down a page #define STB_TEXTEDIT_K_PGDOWN 0x20000F // keyboard input to move cursor down a page
#define STB_TEXTEDIT_K_SHIFT 0x400000 #define STB_TEXTEDIT_K_SHIFT 0x400000
#define STB_TEXTEDIT_IMPLEMENTATION #define IMSTB_TEXTEDIT_IMPLEMENTATION
#define STB_TEXTEDIT_memmove memmove #define IMSTB_TEXTEDIT_memmove memmove
#include "imstb_textedit.h" #include "imstb_textedit.h"
// stb_textedit internally allows for a single undo record to do addition and deletion, but somehow, calling // stb_textedit internally allows for a single undo record to do addition and deletion, but somehow, calling
// the stb_textedit_paste() function creates two separate records, so we perform it manually. (FIXME: Report to nothings/stb?) // the stb_textedit_paste() function creates two separate records, so we perform it manually. (FIXME: Report to nothings/stb?)
static void stb_textedit_replace(ImGuiInputTextState* str, STB_TexteditState* state, const STB_TEXTEDIT_CHARTYPE* text, int text_len) static void stb_textedit_replace(ImGuiInputTextState* str, STB_TexteditState* state, const IMSTB_TEXTEDIT_CHARTYPE* text, int text_len)
{ {
stb_text_makeundo_replace(str, state, 0, str->CurLenW, text_len); stb_text_makeundo_replace(str, state, 0, str->CurLenW, text_len);
ImStb::STB_TEXTEDIT_DELETECHARS(str, 0, str->CurLenW); ImStb::STB_TEXTEDIT_DELETECHARS(str, 0, str->CurLenW);
@@ -3938,8 +3932,8 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, Im
if (c < 0x20) if (c < 0x20)
{ {
bool pass = false; bool pass = false;
pass |= (c == '\n' && (flags & ImGuiInputTextFlags_Multiline)); // Note that an Enter KEY will emit \r and be ignored (we poll for KEY in InputText() code) pass |= (c == '\n') && (flags & ImGuiInputTextFlags_Multiline) != 0; // Note that an Enter KEY will emit \r and be ignored (we poll for KEY in InputText() code)
pass |= (c == '\t' && (flags & ImGuiInputTextFlags_AllowTabInput)); pass |= (c == '\t') && (flags & ImGuiInputTextFlags_AllowTabInput) != 0;
if (!pass) if (!pass)
return false; return false;
apply_named_filters = false; // Override named filters below so newline and tabs can still be inserted. apply_named_filters = false; // Override named filters below so newline and tabs can still be inserted.
@@ -4059,7 +4053,7 @@ static void InputTextReconcileUndoStateAfterUserCallback(ImGuiInputTextState* st
const int insert_len = new_last_diff - first_diff + 1; const int insert_len = new_last_diff - first_diff + 1;
const int delete_len = old_last_diff - first_diff + 1; const int delete_len = old_last_diff - first_diff + 1;
if (insert_len > 0 || delete_len > 0) if (insert_len > 0 || delete_len > 0)
if (STB_TEXTEDIT_CHARTYPE* p = stb_text_createundo(&state->Stb.undostate, first_diff, delete_len, insert_len)) if (IMSTB_TEXTEDIT_CHARTYPE* p = stb_text_createundo(&state->Stb.undostate, first_diff, delete_len, insert_len))
for (int i = 0; i < delete_len; i++) for (int i = 0; i < delete_len; i++)
p[i] = ImStb::STB_TEXTEDIT_GETCHAR(state, first_diff + i); p[i] = ImStb::STB_TEXTEDIT_GETCHAR(state, first_diff + i);
} }
@@ -4111,12 +4105,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
const bool RENDER_SELECTION_WHEN_INACTIVE = false; const bool RENDER_SELECTION_WHEN_INACTIVE = false;
const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0; const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0;
const bool is_readonly = (flags & ImGuiInputTextFlags_ReadOnly) != 0;
const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0;
const bool is_resizable = (flags & ImGuiInputTextFlags_CallbackResize) != 0;
if (is_resizable)
IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag!
if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope (including the scrollbar) if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope (including the scrollbar)
BeginGroup(); BeginGroup();
@@ -4130,7 +4118,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
ImGuiWindow* draw_window = window; ImGuiWindow* draw_window = window;
ImVec2 inner_size = frame_size; ImVec2 inner_size = frame_size;
ImGuiItemStatusFlags item_status_flags = 0;
ImGuiLastItemData item_data_backup; ImGuiLastItemData item_data_backup;
if (is_multiline) if (is_multiline)
{ {
@@ -4141,11 +4128,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
EndGroup(); EndGroup();
return false; return false;
} }
item_status_flags = g.LastItemData.StatusFlags;
item_data_backup = g.LastItemData; item_data_backup = g.LastItemData;
window->DC.CursorPos = backup_pos; window->DC.CursorPos = backup_pos;
// Prevent NavActivate reactivating in BeginChild(). // Prevent NavActivation from Tabbing when our widget accepts Tab inputs: this allows cycling through widgets without stopping.
if (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_FromTabbing) && (flags & ImGuiInputTextFlags_AllowTabInput))
g.NavActivateId = 0;
// Prevent NavActivate reactivating in BeginChild() when we are already active.
const ImGuiID backup_activate_id = g.NavActivateId; const ImGuiID backup_activate_id = g.NavActivateId;
if (g.ActiveId == id) // Prevent reactivation if (g.ActiveId == id) // Prevent reactivation
g.NavActivateId = 0; g.NavActivateId = 0;
@@ -4177,7 +4167,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (!(flags & ImGuiInputTextFlags_MergedItem)) if (!(flags & ImGuiInputTextFlags_MergedItem))
if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable)) if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable))
return false; return false;
item_status_flags = g.LastItemData.StatusFlags;
} }
const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags); const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags);
if (hovered) if (hovered)
@@ -4186,7 +4175,15 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// We are only allowed to access the state if we are already the active widget. // We are only allowed to access the state if we are already the active widget.
ImGuiInputTextState* state = GetInputTextState(id); ImGuiInputTextState* state = GetInputTextState(id);
const bool input_requested_by_tabbing = (item_status_flags & ImGuiItemStatusFlags_FocusedByTabbing) != 0; if (g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly)
flags |= ImGuiInputTextFlags_ReadOnly;
const bool is_readonly = (flags & ImGuiInputTextFlags_ReadOnly) != 0;
const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0;
const bool is_resizable = (flags & ImGuiInputTextFlags_CallbackResize) != 0;
if (is_resizable)
IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag!
const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateId == id) && ((g.NavActivateFlags & ImGuiActivateFlags_PreferInput) || (g.NavInputSource == ImGuiInputSource_Keyboard))); const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateId == id) && ((g.NavActivateFlags & ImGuiActivateFlags_PreferInput) || (g.NavInputSource == ImGuiInputSource_Keyboard)));
const bool user_clicked = hovered && io.MouseClicked[0]; const bool user_clicked = hovered && io.MouseClicked[0];
@@ -4197,27 +4194,32 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX; float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX;
const bool init_reload_from_user_buf = (state != NULL && state->ReloadUserBuf);
const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline); // state != NULL means its our state. const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline); // state != NULL means its our state.
const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav || input_requested_by_tabbing); const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav);
const bool init_state = (init_make_active || user_scroll_active); const bool init_state = (init_make_active || user_scroll_active);
if ((init_state && g.ActiveId != id) || init_changed_specs) if ((init_state && g.ActiveId != id) || init_changed_specs || init_reload_from_user_buf)
{ {
// Access state even if we don't own it yet. // Access state even if we don't own it yet.
state = &g.InputTextState; state = &g.InputTextState;
state->CursorAnimReset(); state->CursorAnimReset();
state->ReloadUserBuf = false;
// Backup state of deactivating item so they'll have a chance to do a write to output buffer on the same frame they report IsItemDeactivatedAfterEdit (#4714) // Backup state of deactivating item so they'll have a chance to do a write to output buffer on the same frame they report IsItemDeactivatedAfterEdit (#4714)
InputTextDeactivateHook(state->ID); InputTextDeactivateHook(state->ID);
// Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar) // From the moment we focused we are normally ignoring the content of 'buf' (unless we are in read-only mode)
// From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode)
const int buf_len = (int)strlen(buf); const int buf_len = (int)strlen(buf);
state->InitialTextA.resize(buf_len + 1); // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string. if (!init_reload_from_user_buf)
memcpy(state->InitialTextA.Data, buf, buf_len + 1); {
// Take a copy of the initial buffer value.
state->InitialTextA.resize(buf_len + 1); // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string.
memcpy(state->InitialTextA.Data, buf, buf_len + 1);
}
// Preserve cursor position and undo/redo stack if we come back to same widget // Preserve cursor position and undo/redo stack if we come back to same widget
// FIXME: Since we reworked this on 2022/06, may want to differenciate recycle_cursor vs recycle_undostate? // FIXME: Since we reworked this on 2022/06, may want to differentiate recycle_cursor vs recycle_undostate?
bool recycle_state = (state->ID == id && !init_changed_specs); bool recycle_state = (state->ID == id && !init_changed_specs && !init_reload_from_user_buf);
if (recycle_state && (state->CurLenA != buf_len || (state->TextAIsValid && strncmp(state->TextA.Data, buf, buf_len) != 0))) if (recycle_state && (state->CurLenA != buf_len || (state->TextAIsValid && strncmp(state->TextA.Data, buf, buf_len) != 0)))
recycle_state = false; recycle_state = false;
@@ -4242,13 +4244,19 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
stb_textedit_initialize_state(&state->Stb, !is_multiline); stb_textedit_initialize_state(&state->Stb, !is_multiline);
} }
if (!is_multiline) if (init_reload_from_user_buf)
{
state->Stb.select_start = state->ReloadSelectionStart;
state->Stb.cursor = state->Stb.select_end = state->ReloadSelectionEnd;
state->CursorClamp();
}
else if (!is_multiline)
{ {
if (flags & ImGuiInputTextFlags_AutoSelectAll) if (flags & ImGuiInputTextFlags_AutoSelectAll)
select_all = true; select_all = true;
if (input_requested_by_nav && (!recycle_state || !(g.NavActivateFlags & ImGuiActivateFlags_TryToPreserveState))) if (input_requested_by_nav && (!recycle_state || !(g.NavActivateFlags & ImGuiActivateFlags_TryToPreserveState)))
select_all = true; select_all = true;
if (input_requested_by_tabbing || (user_clicked && io.KeyCtrl)) if (user_clicked && io.KeyCtrl)
select_all = true; select_all = true;
} }
@@ -4272,6 +4280,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
if (is_multiline || (flags & ImGuiInputTextFlags_CallbackHistory)) if (is_multiline || (flags & ImGuiInputTextFlags_CallbackHistory))
g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
SetKeyOwner(ImGuiKey_Enter, id);
SetKeyOwner(ImGuiKey_KeypadEnter, id);
SetKeyOwner(ImGuiKey_Home, id); SetKeyOwner(ImGuiKey_Home, id);
SetKeyOwner(ImGuiKey_End, id); SetKeyOwner(ImGuiKey_End, id);
if (is_multiline) if (is_multiline)
@@ -4281,8 +4291,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
} }
if (is_osx) if (is_osx)
SetKeyOwner(ImGuiMod_Alt, id); SetKeyOwner(ImGuiMod_Alt, id);
if (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput)) // Disable keyboard tabbing out as we will use the \t character.
SetShortcutRouting(ImGuiKey_Tab, id);
} }
// We have an edge case if ActiveId was set through another widget (e.g. widget being swapped), clear id immediately (don't wait until the end of the function) // We have an edge case if ActiveId was set through another widget (e.g. widget being swapped), clear id immediately (don't wait until the end of the function)
@@ -4411,11 +4419,20 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// We expect backends to emit a Tab key but some also emit a Tab character which we ignore (#2467, #1336) // We expect backends to emit a Tab key but some also emit a Tab character which we ignore (#2467, #1336)
// (For Tab and Enter: Win32/SFML/Allegro are sending both keys and chars, GLFW and SDL are only sending keys. For Space they all send all threes) // (For Tab and Enter: Win32/SFML/Allegro are sending both keys and chars, GLFW and SDL are only sending keys. For Space they all send all threes)
if ((flags & ImGuiInputTextFlags_AllowTabInput) && Shortcut(ImGuiKey_Tab, id) && !is_readonly) if ((flags & ImGuiInputTextFlags_AllowTabInput) && !is_readonly)
{ {
unsigned int c = '\t'; // Insert TAB if (Shortcut(ImGuiKey_Tab, id, ImGuiInputFlags_Repeat))
if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard)) {
state->OnKeyPressed((int)c); unsigned int c = '\t'; // Insert TAB
if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard))
state->OnKeyPressed((int)c);
}
// FIXME: Implement Shift+Tab
/*
if (Shortcut(ImGuiKey_Tab | ImGuiMod_Shift, id, ImGuiInputFlags_Repeat))
{
}
*/
} }
// Process regular text input (before we check for Return because using some IME will effectively send a Return?) // Process regular text input (before we check for Return because using some IME will effectively send a Return?)
@@ -4613,7 +4630,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
apply_new_text = ""; apply_new_text = "";
apply_new_text_length = 0; apply_new_text_length = 0;
value_changed = true; value_changed = true;
STB_TEXTEDIT_CHARTYPE empty_string; IMSTB_TEXTEDIT_CHARTYPE empty_string;
stb_textedit_replace(state, &state->Stb, &empty_string, 0); stb_textedit_replace(state, &state->Stb, &empty_string, 0);
} }
else if (strcmp(buf, state->InitialTextA.Data) != 0) else if (strcmp(buf, state->InitialTextA.Data) != 0)
@@ -4722,7 +4739,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty) { state->Stb.select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb.select_start : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); } if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty) { state->Stb.select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb.select_start : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); }
if (buf_dirty) if (buf_dirty)
{ {
IM_ASSERT((flags & ImGuiInputTextFlags_ReadOnly) == 0); IM_ASSERT(!is_readonly);
IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text! IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
InputTextReconcileUndoStateAfterUserCallback(state, callback_data.Buf, callback_data.BufTextLen); // FIXME: Move the rest of this block inside function and rename to InputTextReconcileStateAfterUserCallback() ? InputTextReconcileUndoStateAfterUserCallback(state, callback_data.Buf, callback_data.BufTextLen); // FIXME: Move the rest of this block inside function and rename to InputTextReconcileStateAfterUserCallback() ?
if (callback_data.BufTextLen > backup_current_text_length && is_resizable) if (callback_data.BufTextLen > backup_current_text_length && is_resizable)
@@ -5053,10 +5070,10 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state)
Text("CurLenW: %d, CurLenA: %d, Cursor: %d, Selection: %d..%d", state->CurLenW, state->CurLenA, stb_state->cursor, stb_state->select_start, stb_state->select_end); Text("CurLenW: %d, CurLenA: %d, Cursor: %d, Selection: %d..%d", state->CurLenW, state->CurLenA, stb_state->cursor, stb_state->select_start, stb_state->select_end);
Text("has_preferred_x: %d (%.2f)", stb_state->has_preferred_x, stb_state->preferred_x); Text("has_preferred_x: %d (%.2f)", stb_state->has_preferred_x, stb_state->preferred_x);
Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state->undo_point, undo_state->redo_point, undo_state->undo_char_point, undo_state->redo_char_point); Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state->undo_point, undo_state->redo_point, undo_state->undo_char_point, undo_state->redo_char_point);
if (BeginChild("undopoints", ImVec2(0.0f, GetTextLineHeight() * 15), ImGuiChildFlags_Border)) // Visualize undo state if (BeginChild("undopoints", ImVec2(0.0f, GetTextLineHeight() * 10), ImGuiChildFlags_Border | ImGuiChildFlags_ResizeY)) // Visualize undo state
{ {
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
for (int n = 0; n < STB_TEXTEDIT_UNDOSTATECOUNT; n++) for (int n = 0; n < IMSTB_TEXTEDIT_UNDOSTATECOUNT; n++)
{ {
ImStb::StbUndoRecord* undo_rec = &undo_state->undo_rec[n]; ImStb::StbUndoRecord* undo_rec = &undo_state->undo_rec[n];
const char undo_rec_type = (n < undo_state->undo_point) ? 'u' : (n >= undo_state->redo_point) ? 'r' : ' '; const char undo_rec_type = (n < undo_state->undo_point) ? 'u' : (n >= undo_state->redo_point) ? 'r' : ' ';
@@ -5138,10 +5155,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style; const ImGuiStyle& style = g.Style;
const float square_sz = GetFrameHeight(); const float square_sz = GetFrameHeight();
const float w_full = CalcItemWidth();
const float w_button = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x);
const float w_inputs = w_full - w_button;
const char* label_display_end = FindRenderedTextEnd(label); const char* label_display_end = FindRenderedTextEnd(label);
float w_full = CalcItemWidth();
g.NextItemData.ClearFlags(); g.NextItemData.ClearFlags();
BeginGroup(); BeginGroup();
@@ -5175,6 +5190,9 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
const bool alpha = (flags & ImGuiColorEditFlags_NoAlpha) == 0; const bool alpha = (flags & ImGuiColorEditFlags_NoAlpha) == 0;
const bool hdr = (flags & ImGuiColorEditFlags_HDR) != 0; const bool hdr = (flags & ImGuiColorEditFlags_HDR) != 0;
const int components = alpha ? 4 : 3; const int components = alpha ? 4 : 3;
const float w_button = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x);
const float w_inputs = ImMax(w_full - w_button, 1.0f);
w_full = w_inputs + w_button;
// Convert to the formats we need // Convert to the formats we need
float f[4] = { col[0], col[1], col[2], alpha ? col[3] : 1.0f }; float f[4] = { col[0], col[1], col[2], alpha ? col[3] : 1.0f };
@@ -5198,10 +5216,9 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
if ((flags & (ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV)) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0) if ((flags & (ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV)) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0)
{ {
// RGB/HSV 0..255 Sliders // RGB/HSV 0..255 Sliders
const float w_item_one = ImMax(1.0f, IM_TRUNC((w_inputs - (style.ItemInnerSpacing.x) * (components - 1)) / (float)components)); const float w_items = w_inputs - style.ItemInnerSpacing.x * (components - 1);
const float w_item_last = ImMax(1.0f, IM_TRUNC(w_inputs - (w_item_one + style.ItemInnerSpacing.x) * (components - 1)));
const bool hide_prefix = (w_item_one <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? "M:0.000" : "M:000").x); const bool hide_prefix = (IM_TRUNC(w_items / components) <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? "M:0.000" : "M:000").x);
static const char* ids[4] = { "##X", "##Y", "##Z", "##W" }; static const char* ids[4] = { "##X", "##Y", "##Z", "##W" };
static const char* fmt_table_int[3][4] = static const char* fmt_table_int[3][4] =
{ {
@@ -5217,11 +5234,14 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
}; };
const int fmt_idx = hide_prefix ? 0 : (flags & ImGuiColorEditFlags_DisplayHSV) ? 2 : 1; const int fmt_idx = hide_prefix ? 0 : (flags & ImGuiColorEditFlags_DisplayHSV) ? 2 : 1;
float prev_split = 0.0f;
for (int n = 0; n < components; n++) for (int n = 0; n < components; n++)
{ {
if (n > 0) if (n > 0)
SameLine(0, style.ItemInnerSpacing.x); SameLine(0, style.ItemInnerSpacing.x);
SetNextItemWidth((n + 1 < components) ? w_item_one : w_item_last); float next_split = IM_TRUNC(w_items * (n + 1) / components);
SetNextItemWidth(ImMax(next_split - prev_split, 1.0f));
prev_split = next_split;
// FIXME: When ImGuiColorEditFlags_HDR flag is passed HS values snap in weird ways when SV values go below 0. // FIXME: When ImGuiColorEditFlags_HDR flag is passed HS values snap in weird ways when SV values go below 0.
if (flags & ImGuiColorEditFlags_Float) if (flags & ImGuiColorEditFlags_Float)
@@ -5246,7 +5266,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
else else
ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp(i[0], 0, 255), ImClamp(i[1], 0, 255), ImClamp(i[2], 0, 255)); ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp(i[0], 0, 255), ImClamp(i[1], 0, 255), ImClamp(i[2], 0, 255));
SetNextItemWidth(w_inputs); SetNextItemWidth(w_inputs);
if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase)) if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsUppercase))
{ {
value_changed = true; value_changed = true;
char* p = buf; char* p = buf;
@@ -5344,7 +5364,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
// Drag and Drop Target // Drag and Drop Target
// NB: The flag test is merely an optional micro-optimization, BeginDragDropTarget() does the same test. // NB: The flag test is merely an optional micro-optimization, BeginDragDropTarget() does the same test.
if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropTarget()) if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) && !(g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropTarget())
{ {
bool accepted_drag_drop = false; bool accepted_drag_drop = false;
if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
@@ -5409,6 +5429,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
ImGuiIO& io = g.IO; ImGuiIO& io = g.IO;
const float width = CalcItemWidth(); const float width = CalcItemWidth();
const bool is_readonly = ((g.NextItemData.ItemFlags | g.CurrentItemFlags) & ImGuiItemFlags_ReadOnly) != 0;
g.NextItemData.ClearFlags(); g.NextItemData.ClearFlags();
PushID(label); PushID(label);
@@ -5479,7 +5500,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
{ {
// Hue wheel + SV triangle logic // Hue wheel + SV triangle logic
InvisibleButton("hsv", ImVec2(sv_picker_size + style.ItemInnerSpacing.x + bars_width, sv_picker_size)); InvisibleButton("hsv", ImVec2(sv_picker_size + style.ItemInnerSpacing.x + bars_width, sv_picker_size));
if (IsItemActive()) if (IsItemActive() && !is_readonly)
{ {
ImVec2 initial_off = g.IO.MouseClickedPos[0] - wheel_center; ImVec2 initial_off = g.IO.MouseClickedPos[0] - wheel_center;
ImVec2 current_off = g.IO.MousePos - wheel_center; ImVec2 current_off = g.IO.MousePos - wheel_center;
@@ -5514,7 +5535,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
{ {
// SV rectangle logic // SV rectangle logic
InvisibleButton("sv", ImVec2(sv_picker_size, sv_picker_size)); InvisibleButton("sv", ImVec2(sv_picker_size, sv_picker_size));
if (IsItemActive()) if (IsItemActive() && !is_readonly)
{ {
S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size - 1)); S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size - 1));
V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1)); V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1));
@@ -5527,7 +5548,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
// Hue bar logic // Hue bar logic
SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y)); SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y));
InvisibleButton("hue", ImVec2(bars_width, sv_picker_size)); InvisibleButton("hue", ImVec2(bars_width, sv_picker_size));
if (IsItemActive()) if (IsItemActive() && !is_readonly)
{ {
H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1)); H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1));
value_changed = value_changed_h = true; value_changed = value_changed_h = true;
@@ -5733,7 +5754,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
} }
// Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range) // Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range)
float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f; float sv_cursor_rad = value_changed_sv ? wheel_thickness * 0.55f : wheel_thickness * 0.40f;
int sv_cursor_segments = draw_list->_CalcCircleAutoSegmentCount(sv_cursor_rad); // Lock segment count so the +1 one matches others. int sv_cursor_segments = draw_list->_CalcCircleAutoSegmentCount(sv_cursor_rad); // Lock segment count so the +1 one matches others.
draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, sv_cursor_segments); draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, sv_cursor_segments);
draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad + 1, col_midgrey, sv_cursor_segments); draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad + 1, col_midgrey, sv_cursor_segments);
@@ -6239,7 +6260,11 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
} }
if (span_all_columns) if (span_all_columns)
{
TablePushBackgroundChannel(); TablePushBackgroundChannel();
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasClipRect;
g.LastItemData.ClipRect = window->ClipRect;
}
ImGuiButtonFlags button_flags = ImGuiTreeNodeFlags_None; ImGuiButtonFlags button_flags = ImGuiTreeNodeFlags_None;
if ((flags & ImGuiTreeNodeFlags_AllowOverlap) || (g.LastItemData.InFlags & ImGuiItemFlags_AllowOverlap)) if ((flags & ImGuiTreeNodeFlags_AllowOverlap) || (g.LastItemData.InFlags & ImGuiItemFlags_AllowOverlap))
@@ -6323,7 +6348,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
// Render // Render
const ImU32 text_col = GetColorU32(ImGuiCol_Text); const ImU32 text_col = GetColorU32(ImGuiCol_Text);
ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_TypeThin; ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_Compact;
if (display_frame) if (display_frame)
{ {
// Framed type // Framed type
@@ -6468,7 +6493,7 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFl
ImGuiID id = window->GetID(label); ImGuiID id = window->GetID(label);
flags |= ImGuiTreeNodeFlags_CollapsingHeader; flags |= ImGuiTreeNodeFlags_CollapsingHeader;
if (p_visible) if (p_visible)
flags |= ImGuiTreeNodeFlags_AllowOverlap | ImGuiTreeNodeFlags_ClipLabelForTrailingButton; flags |= ImGuiTreeNodeFlags_AllowOverlap | (ImGuiTreeNodeFlags)ImGuiTreeNodeFlags_ClipLabelForTrailingButton;
bool is_open = TreeNodeBehavior(id, flags, label); bool is_open = TreeNodeBehavior(id, flags, label);
if (p_visible != NULL) if (p_visible != NULL)
{ {
@@ -6569,10 +6594,15 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
// FIXME: We can standardize the behavior of those two, we could also keep the fast path of override ClipRect + full push on render only, // FIXME: We can standardize the behavior of those two, we could also keep the fast path of override ClipRect + full push on render only,
// which would be advantageous since most selectable are not selected. // which would be advantageous since most selectable are not selected.
if (span_all_columns && window->DC.CurrentColumns) if (span_all_columns)
PushColumnsBackground(); {
else if (span_all_columns && g.CurrentTable) if (g.CurrentTable)
TablePushBackgroundChannel(); TablePushBackgroundChannel();
else if (window->DC.CurrentColumns)
PushColumnsBackground();
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasClipRect;
g.LastItemData.ClipRect = window->ClipRect;
}
// We use NoHoldingActiveID on menus so user can click and _hold_ on a menu then drag to browse child entries // We use NoHoldingActiveID on menus so user can click and _hold_ on a menu then drag to browse child entries
ImGuiButtonFlags button_flags = 0; ImGuiButtonFlags button_flags = 0;
@@ -6621,12 +6651,15 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
RenderFrame(bb.Min, bb.Max, col, false, 0.0f); RenderFrame(bb.Min, bb.Max, col, false, 0.0f);
} }
if (g.NavId == id) if (g.NavId == id)
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_Compact | ImGuiNavHighlightFlags_NoRounding);
if (span_all_columns && window->DC.CurrentColumns) if (span_all_columns)
PopColumnsBackground(); {
else if (span_all_columns && g.CurrentTable) if (g.CurrentTable)
TablePopBackgroundChannel(); TablePopBackgroundChannel();
else if (window->DC.CurrentColumns)
PopColumnsBackground();
}
RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb); RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb);
@@ -7502,6 +7535,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
PopItemFlag(); PopItemFlag();
bool want_open = false; bool want_open = false;
bool want_open_nav_init = false;
bool want_close = false; bool want_close = false;
if (window->DC.LayoutType == ImGuiLayoutType_Vertical) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) if (window->DC.LayoutType == ImGuiLayoutType_Vertical) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu))
{ {
@@ -7512,18 +7546,18 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
ImGuiWindow* child_menu_window = (child_popup && child_popup->Window && child_popup->Window->ParentWindow == window) ? child_popup->Window : NULL; ImGuiWindow* child_menu_window = (child_popup && child_popup->Window && child_popup->Window->ParentWindow == window) ? child_popup->Window : NULL;
if (g.HoveredWindow == window && child_menu_window != NULL) if (g.HoveredWindow == window && child_menu_window != NULL)
{ {
float ref_unit = g.FontSize; // FIXME-DPI const float ref_unit = g.FontSize; // FIXME-DPI
float child_dir = (window->Pos.x < child_menu_window->Pos.x) ? 1.0f : -1.0f; const float child_dir = (window->Pos.x < child_menu_window->Pos.x) ? 1.0f : -1.0f;
ImRect next_window_rect = child_menu_window->Rect(); const ImRect next_window_rect = child_menu_window->Rect();
ImVec2 ta = (g.IO.MousePos - g.IO.MouseDelta); ImVec2 ta = (g.IO.MousePos - g.IO.MouseDelta);
ImVec2 tb = (child_dir > 0.0f) ? next_window_rect.GetTL() : next_window_rect.GetTR(); ImVec2 tb = (child_dir > 0.0f) ? next_window_rect.GetTL() : next_window_rect.GetTR();
ImVec2 tc = (child_dir > 0.0f) ? next_window_rect.GetBL() : next_window_rect.GetBR(); ImVec2 tc = (child_dir > 0.0f) ? next_window_rect.GetBL() : next_window_rect.GetBR();
float extra = ImClamp(ImFabs(ta.x - tb.x) * 0.30f, ref_unit * 0.5f, ref_unit * 2.5f); // add a bit of extra slack. const float pad_farmost_h = ImClamp(ImFabs(ta.x - tb.x) * 0.30f, ref_unit * 0.5f, ref_unit * 2.5f); // Add a bit of extra slack.
ta.x += child_dir * -0.5f; ta.x += child_dir * -0.5f;
tb.x += child_dir * ref_unit; tb.x += child_dir * ref_unit;
tc.x += child_dir * ref_unit; tc.x += child_dir * ref_unit;
tb.y = ta.y + ImMax((tb.y - extra) - ta.y, -ref_unit * 8.0f); // triangle has maximum height to limit the slope and the bias toward large sub-menus tb.y = ta.y + ImMax((tb.y - pad_farmost_h) - ta.y, -ref_unit * 8.0f); // Triangle has maximum height to limit the slope and the bias toward large sub-menus
tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +ref_unit * 8.0f); tc.y = ta.y + ImMin((tc.y + pad_farmost_h) - ta.y, +ref_unit * 8.0f);
moving_toward_child_menu = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos); moving_toward_child_menu = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos);
//GetForegroundDrawList()->AddTriangleFilled(ta, tb, tc, moving_toward_child_menu ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); // [DEBUG] //GetForegroundDrawList()->AddTriangleFilled(ta, tb, tc, moving_toward_child_menu ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); // [DEBUG]
} }
@@ -7535,14 +7569,18 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
want_close = true; want_close = true;
// Open // Open
// (note: at this point 'hovered' actually includes the NavDisableMouseHover == false test)
if (!menu_is_open && pressed) // Click/activate to open if (!menu_is_open && pressed) // Click/activate to open
want_open = true; want_open = true;
else if (!menu_is_open && hovered && !moving_toward_child_menu) // Hover to open else if (!menu_is_open && hovered && !moving_toward_child_menu) // Hover to open
want_open = true; want_open = true;
else if (!menu_is_open && hovered && g.HoveredIdTimer >= 0.30f && g.MouseStationaryTimer >= 0.30f) // Hover to open (timer fallback)
want_open = true;
if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open
{ {
want_open = true; want_open = want_open_nav_init = true;
NavMoveRequestCancel(); NavMoveRequestCancel();
NavRestoreHighlightAfterMove();
} }
} }
else else
@@ -7574,13 +7612,13 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
if (want_open && !menu_is_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size) if (want_open && !menu_is_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size)
{ {
// Don't reopen/recycle same menu level in the same frame, first close the other menu and yield for a frame. // Don't reopen/recycle same menu level in the same frame if it is a different menu ID, first close the other menu and yield for a frame.
OpenPopup(label); OpenPopup(label);
} }
else if (want_open) else if (want_open)
{ {
menu_is_open = true; menu_is_open = true;
OpenPopup(label); OpenPopup(label, ImGuiPopupFlags_NoReopen);// | (want_open_nav_init ? ImGuiPopupFlags_NoReopenAlwaysNavInit : 0));
} }
if (menu_is_open) if (menu_is_open)
@@ -7592,6 +7630,14 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
PopStyleVar(); PopStyleVar();
if (menu_is_open) if (menu_is_open)
{ {
// Implement what ImGuiPopupFlags_NoReopenAlwaysNavInit would do:
// Perform an init request in the case the popup was already open (via a previous mouse hover)
if (want_open && want_open_nav_init && !g.NavInitRequest)
{
FocusWindow(g.CurrentWindow, ImGuiFocusRequestFlags_UnlessBelowModal);
NavInitWindow(g.CurrentWindow, false);
}
// Restore LastItemData so IsItemXXXX functions can work after BeginMenu()/EndMenu() // Restore LastItemData so IsItemXXXX functions can work after BeginMenu()/EndMenu()
// (This fixes using IsItemClicked() and IsItemHovered(), but IsItemHovered() also relies on its support for ImGuiItemFlags_NoWindowHoverableCheck) // (This fixes using IsItemClicked() and IsItemHovered(), but IsItemHovered() also relies on its support for ImGuiItemFlags_NoWindowHoverableCheck)
g.LastItemData = last_item_in_parent; g.LastItemData = last_item_in_parent;
@@ -8293,7 +8339,7 @@ void ImGui::TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
if (tab->Flags & ImGuiTabItemFlags_Button) if (tab->Flags & ImGuiTabItemFlags_Button)
return; // A button appended with TabItemButton(). return; // A button appended with TabItemButton().
if (!(tab->Flags & ImGuiTabItemFlags_UnsavedDocument)) if ((tab->Flags & (ImGuiTabItemFlags_UnsavedDocument | ImGuiTabItemFlags_NoAssumedClosure)) == 0)
{ {
// This will remove a frame of lag for selecting another tab on closure. // This will remove a frame of lag for selecting another tab on closure.
// However we don't run it in the case where the 'Unsaved' flag is set, so user gets a chance to fully undo the closure // However we don't run it in the case where the 'Unsaved' flag is set, so user gets a chance to fully undo the closure

View File

@@ -4,6 +4,7 @@
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321) // - 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) // - 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. // 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 // stb_textedit.h - v1.14 - public domain - Sean Barrett
// Development of this library was sponsored by RAD Game Tools // Development of this library was sponsored by RAD Game Tools
@@ -30,7 +31,7 @@
// DEPENDENCIES // DEPENDENCIES
// //
// Uses the C runtime function 'memmove', which you can override // 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. // Uses no other functions. Performs no runtime allocations.
// //
// //
@@ -274,8 +275,8 @@
//// ////
//// ////
#ifndef INCLUDE_STB_TEXTEDIT_H #ifndef INCLUDE_IMSTB_TEXTEDIT_H
#define INCLUDE_STB_TEXTEDIT_H #define INCLUDE_IMSTB_TEXTEDIT_H
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// //
@@ -286,33 +287,33 @@
// and undo state. // and undo state.
// //
#ifndef STB_TEXTEDIT_UNDOSTATECOUNT #ifndef IMSTB_TEXTEDIT_UNDOSTATECOUNT
#define STB_TEXTEDIT_UNDOSTATECOUNT 99 #define IMSTB_TEXTEDIT_UNDOSTATECOUNT 99
#endif #endif
#ifndef STB_TEXTEDIT_UNDOCHARCOUNT #ifndef IMSTB_TEXTEDIT_UNDOCHARCOUNT
#define STB_TEXTEDIT_UNDOCHARCOUNT 999 #define IMSTB_TEXTEDIT_UNDOCHARCOUNT 999
#endif #endif
#ifndef STB_TEXTEDIT_CHARTYPE #ifndef IMSTB_TEXTEDIT_CHARTYPE
#define STB_TEXTEDIT_CHARTYPE int #define IMSTB_TEXTEDIT_CHARTYPE int
#endif #endif
#ifndef STB_TEXTEDIT_POSITIONTYPE #ifndef IMSTB_TEXTEDIT_POSITIONTYPE
#define STB_TEXTEDIT_POSITIONTYPE int #define IMSTB_TEXTEDIT_POSITIONTYPE int
#endif #endif
typedef struct typedef struct
{ {
// private data // private data
STB_TEXTEDIT_POSITIONTYPE where; IMSTB_TEXTEDIT_POSITIONTYPE where;
STB_TEXTEDIT_POSITIONTYPE insert_length; IMSTB_TEXTEDIT_POSITIONTYPE insert_length;
STB_TEXTEDIT_POSITIONTYPE delete_length; IMSTB_TEXTEDIT_POSITIONTYPE delete_length;
int char_storage; int char_storage;
} StbUndoRecord; } StbUndoRecord;
typedef struct typedef struct
{ {
// private data // private data
StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT]; StbUndoRecord undo_rec [IMSTB_TEXTEDIT_UNDOSTATECOUNT];
STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT]; IMSTB_TEXTEDIT_CHARTYPE undo_char[IMSTB_TEXTEDIT_UNDOCHARCOUNT];
short undo_point, redo_point; short undo_point, redo_point;
int undo_char_point, redo_char_point; int undo_char_point, redo_char_point;
} StbUndoState; } StbUndoState;
@@ -371,7 +372,7 @@ typedef struct
float ymin,ymax; // height of row above and below baseline float ymin,ymax; // height of row above and below baseline
int num_chars; int num_chars;
} StbTexteditRow; } 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 // implementation isn't include-guarded, since it might have indirectly
// included just the "header" portion // included just the "header" portion
#ifdef STB_TEXTEDIT_IMPLEMENTATION #ifdef IMSTB_TEXTEDIT_IMPLEMENTATION
#ifndef STB_TEXTEDIT_memmove #ifndef IMSTB_TEXTEDIT_memmove
#include <string.h> #include <string.h>
#define STB_TEXTEDIT_memmove memmove #define IMSTB_TEXTEDIT_memmove memmove
#endif #endif
@@ -398,7 +399,7 @@ typedef struct
// //
// traverse the layout to locate the nearest character to a display position // 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; StbTexteditRow r;
int n = STB_TEXTEDIT_STRINGLEN(str); 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 // 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 // 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 // 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 // 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; int p = 0;
@@ -502,11 +503,11 @@ static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state
// //
// forward declarations // forward declarations
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state); static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state);
static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state); static void stb_text_redo(IMSTB_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_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_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 typedef struct
{ {
@@ -518,7 +519,7 @@ typedef struct
// find the x/y location of a character, and remember info about the previous row in // 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) // 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; StbTexteditRow r;
int prev_start = 0; 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) #define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
// make the selection/cursor state valid if client altered the string // 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); int n = STB_TEXTEDIT_STRINGLEN(str);
if (STB_TEXT_HAS_SELECTION(state)) { 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 // 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_text_makeundo_delete(str, state, where, len);
STB_TEXTEDIT_DELETECHARS(str, 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 // 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); stb_textedit_clamp(str, state);
if (STB_TEXT_HAS_SELECTION(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 // 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)) { if (STB_TEXT_HAS_SELECTION(state)) {
stb_textedit_sortselection(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 #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; 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 #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 --c; // always move at least one character
while( c >= 0 && !is_word_boundary( str, c ) ) 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 #endif
#ifndef STB_TEXTEDIT_MOVEWORDRIGHT #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); const int len = STB_TEXTEDIT_STRINGLEN(str);
++c; // always move at least one character ++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 // 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)) { if (STB_TEXT_HAS_SELECTION(state)) {
stb_textedit_delete_selection(str,state); // implicitly clamps 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 // 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 // if there's a selection, the paste should delete it
stb_textedit_clamp(str, state); stb_textedit_clamp(str, state);
@@ -720,14 +721,14 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta
#endif #endif
// API key: process a keyboard input // 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: retry:
switch (key) { switch (key) {
default: { default: {
int c = STB_TEXTEDIT_KEYTOTEXT(key); int c = STB_TEXTEDIT_KEYTOTEXT(key);
if (c > 0) { 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 // can't add newline in single-line mode
if (c == '\n' && state->single_line) if (c == '\n' && state->single_line)
@@ -892,8 +893,8 @@ retry:
x = row.x0; x = row.x0;
for (i=0; i < row.num_chars; ++i) { for (i=0; i < row.num_chars; ++i) {
float dx = STB_TEXTEDIT_GETWIDTH(str, start, i); float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE #ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
break; break;
#endif #endif
x += dx; x += dx;
@@ -954,8 +955,8 @@ retry:
x = row.x0; x = row.x0;
for (i=0; i < row.num_chars; ++i) { for (i=0; i < row.num_chars; ++i) {
float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i); float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE #ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
break; break;
#endif #endif
x += dx; x += dx;
@@ -1112,8 +1113,8 @@ retry:
static void stb_textedit_flush_redo(StbUndoState *state) static void stb_textedit_flush_redo(StbUndoState *state)
{ {
state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; state->redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT;
state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; state->redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT;
} }
// discard the oldest entry in the undo list // 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; int n = state->undo_rec[0].insert_length, i;
// delete n characters from all other records // delete n characters from all other records
state->undo_char_point -= n; 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) for (i=0; i < state->undo_point; ++i)
if (state->undo_rec[i].char_storage >= 0) 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_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it
} }
--state->undo_point; --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 // fill up even though the undo buffer didn't
static void stb_textedit_discard_redo(StbUndoState *state) 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 (state->redo_point <= k) {
// if the k'th undo state has characters, clean those up // 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; int n = state->undo_rec[k].insert_length, i;
// move the remaining redo character data to the end of the buffer // move the remaining redo character data to the end of the buffer
state->redo_char_point += n; 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 // adjust the position of all the other records to account for above memmove
for (i=state->redo_point; i < k; ++i) for (i=state->redo_point; i < k; ++i)
if (state->undo_rec[i].char_storage >= 0) 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' // now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
// [DEAR IMGUI] // [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_begin = (char*)state->undo_rec; (void)buf_begin;
const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end; 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)) >= buf_begin);
IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end); 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 // now move redo_point to point to the new one
++state->redo_point; ++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 // if we have no free records, we have to make room, by sliding the
// existing records down // existing records down
if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT) if (state->undo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
stb_textedit_discard_undo(state); stb_textedit_discard_undo(state);
// if the characters to store won't possibly fit in the buffer, we can't undo // 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_point = 0;
state->undo_char_point = 0; state->undo_char_point = 0;
return NULL; return NULL;
} }
// if we don't have enough free characters in the buffer, we have to make room // 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); stb_textedit_discard_undo(state);
return &state->undo_rec[state->undo_point++]; 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); StbUndoRecord *r = stb_text_create_undo_record(state, insert_len);
if (r == NULL) if (r == NULL)
return NULL; return NULL;
r->where = pos; r->where = pos;
r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len; r->insert_length = (IMSTB_TEXTEDIT_POSITIONTYPE) insert_len;
r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len; r->delete_length = (IMSTB_TEXTEDIT_POSITIONTYPE) delete_len;
if (insert_len == 0) { if (insert_len == 0) {
r->char_storage = -1; 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; StbUndoState *s = &state->undostate;
StbUndoRecord u, *r; 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 // characters stored for *undoing* don't leave room for redo
// if the last is true, we have to bail // 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 // the undo records take up too much character space; there's no space to store the redo characters
r->insert_length = 0; r->insert_length = 0;
} else { } 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 // there's definitely room to store the characters eventually
while (s->undo_char_point + u.delete_length > s->redo_char_point) { while (s->undo_char_point + u.delete_length > s->redo_char_point) {
// should never happen: // should never happen:
if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
return; return;
// there's currently not enough room, so discard a redo record // there's currently not enough room, so discard a redo record
stb_textedit_discard_redo(s); stb_textedit_discard_redo(s);
@@ -1281,11 +1282,11 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
s->redo_point--; 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; StbUndoState *s = &state->undostate;
StbUndoRecord *u, r; StbUndoRecord *u, r;
if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
return; return;
// we need to do two things: apply the redo record, and create an undo record // 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); 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; 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) { if (p) {
for (i=0; i < length; ++i) for (i=0; i < length; ++i)
p[i] = STB_TEXTEDIT_GETCHAR(str, where+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; 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) { if (p) {
for (i=0; i < old_length; ++i) for (i=0; i < old_length; ++i)
p[i] = STB_TEXTEDIT_GETCHAR(str, where+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_point = 0;
state->undostate.undo_char_point = 0; state->undostate.undo_char_point = 0;
state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; state->undostate.redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT;
state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; state->undostate.redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT;
state->select_end = state->select_start = 0; state->select_end = state->select_start = 0;
state->cursor = 0; state->cursor = 0;
state->has_preferred_x = 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" #pragma GCC diagnostic ignored "-Wcast-qual"
#endif #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__) #if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
#endif//STB_TEXTEDIT_IMPLEMENTATION #endif//IMSTB_TEXTEDIT_IMPLEMENTATION
/* /*
------------------------------------------------------------------------------ ------------------------------------------------------------------------------

View File

@@ -437,7 +437,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
ImFontAtlasBuildInit(atlas); ImFontAtlasBuildInit(atlas);
// Clear atlas // Clear atlas
atlas->TexID = (ImTextureID)nullptr; atlas->TexID = 0;
atlas->TexWidth = atlas->TexHeight = 0; atlas->TexWidth = atlas->TexHeight = 0;
atlas->TexUvScale = ImVec2(0.0f, 0.0f); atlas->TexUvScale = ImVec2(0.0f, 0.0f);
atlas->TexUvWhitePixel = 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); 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) // Obsolete names (will be removed soon)
// Prefer using '#define IMGUI_ENABLE_FREETYPE'
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #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 #endif
} }