Compare commits

..

162 Commits

Author SHA1 Message Date
30f2ca893f WIP insert mode (2863)
missing cursor rendering (keep caret when on carriage return)
missing storage of insert state
2021-03-12 18:56:40 +01:00
287bd9b984 InputText: renamed ImGuiInputTextFlags_AlwaysInsertMode to ImGuiInputTextFlags_AlwaysOverwrite. (#2863) 2021-03-12 18:23:30 +01:00
1bc6f82091 Misc: added imgui.gdb and imgui.natstepfilter debugger helpers for gdb and msvc. 2021-03-12 17:03:16 +01:00
033dfd9d35 ImDrawFlags: rework/revert c2d6d26 + 39432bf in a way that is closer to old version and back to opt-in but with default 0 = all corners. 2021-03-12 16:31:46 +01:00
fdc2324d9a Moved 'misc/natvis/imgui.natvis' to 'misc/debuggers/imgui.natvis' 2021-03-11 16:21:46 +01:00
39432bfd9c Amend 0c93238a ImDrawList: upgraded AddRect(), AddRectFilled(), PathRect() to use general ImDrawFlags instead of ImDrawCornersFlags 2021-03-11 16:03:45 +01:00
c2d6d26139 ImDrawList: upgraded AddRect(), AddRectFilled(), PathRect() to use general ImDrawFlags instead of ImDrawCornersFlags 2021-03-11 16:03:32 +01:00
8b9fedba28 Moved Obsolete function block lower in the file + obsoleted old SetScrollHere (->SetScrollHereY) 2021-03-11 12:16:52 +01:00
e45847d99a Add version of PathArcTo() and PathArcToFast() with adaptive rendering quality. (#3491) 2021-03-11 11:23:55 +01:00
8ed34af6f8 ImDrawList: clarified that PathArcTo()/PathArcToFast() cannot take radius < 0.0f. (#3491) + changed poor-man ceiling in _CalcCircleAutoSegmentCount() to use 0.999999f to reduce gaps
Previously it sorts of accidentally worked but would lead to counter-clockwise paths which and have an effect on anti-aliasing.
2021-03-11 10:51:20 +01:00
a3ebd160cb Fix unused variable warning in ImGui::EndListBox() (#3897) 2021-03-11 10:04:50 +01:00
6ba1334903 Nav: internals: renaming ImGuiInputSource so it is not specific to nav. Comments. 2021-03-10 16:36:39 +01:00
01a2bac7d5 DrawList: Replace "bool close" in drawing functions with flags. 2021-03-10 12:57:01 +01:00
a64e0eb3a4 Nav: merged SetNavID() and SetNavIDWithRectRel() to improve sanity, moved flags overwrite off them. (#787) 2021-03-09 17:21:01 +01:00
1c9cc7c117 Nav: tweaks so docking can use same code. NavRestoreLayer restore nav id but Menu key typicallys clears it for menu layer (+ less relying on _ChildWindow flag). 2021-03-09 16:57:13 +01:00
4bb5a36f90 Nav: do not clear per-window NavId when window reappears. Process NavInit regardless of current highllight state. Consistently set g.NavLayer in SetNavID(). (#787) 2021-03-09 12:39:18 +01:00
954b06afe2 Drag and Drop: can use BeginDragDropSource() for other than the left mouse button (#1637, #3885)
As long as the item has an ID (for ID-less items will add new functionalities later.
Amend 2c3c5125
2021-03-08 15:50:53 +01:00
e842b196df Amend sanitization of format strings. Support ' without stb_printf. Simpler loops, will also be used for ImStrv branch. (8ee77f1) (#3604)
Widgets: Sliders: Fix a bug where numbers after format specifier (eg. %d123) would cause RoundScalarWithFormatT() return incorrect value.
2021-03-05 18:27:35 +01:00
8ee77f1b65 Widgets: Sliders: Skip custom stb_sprintf.h format flags (', #, _) in RoundScalarWithFormatT() as they break ImAtof()/ImAtoi() and cause Drag*()/Slider*() widgets display incorrect values. (#3604)
Widgets: Sliders: Fix a bug where numbers after format specifier (eg. %d123) would cause RoundScalarWithFormatT() return incorrect value.
2021-03-05 18:06:54 +01:00
fdebb2e093 Internals: removed HoveredRootWindow, tweak IsWindowHovered(). 2021-03-05 15:56:59 +01:00
f5bc5e8630 Freetype: Enable FreeType bitmap glyphs. (#3879) 2021-03-05 14:25:27 +01:00
ee643b2ad9 IsItemHovered(): fixed return value false positive when used after EndChild(), EndGroup() or widgets using either... (#3851, #1370)
...when the hovered location is located within a child window, e.g. InputTextMultiline().
This is intended to have no side effects, but brace yourself for the possible comeback..
This essentially makes IsItemHovered() not accept hover from child windows, but EndChild/EndGroup are forwarded.
More or less should fix/revert c76f014292 which was a revert of 344d48be3
2021-03-04 19:59:59 +01:00
b53b8f58df Demo: Use correct string formats on non-windows platforms.
(amended)
2021-03-04 18:40:46 +01:00
3e6dfd3c1a ImDrawList: AddImageRounded() compare texid from cmdheader as with other functions. + Made the ImGuiMemAllocFunc / ImGuiMemFreeFunc consistent with our other typedefs (#3836) 2021-03-04 14:29:01 +01:00
8dd692c29c Android: Amend backend and examples with minor consistency tweaks. (#3446) 2021-03-04 11:07:03 +01:00
fb85c0341b Add Android backend and example (#3446) 2021-03-04 10:35:44 +01:00
d8c88bd943 Tables: Fixed unaligned accesses when using TableSetBgColor(ImGuiTableBgTarget_CellBg). (#3872)
ImSpanAllocator: Support for alignment.
2021-03-04 09:52:03 +01:00
1ddaff83d8 Demo: Tweak inputs display. 2021-03-03 18:45:52 +01:00
662535f357 Backends: DX9: Fix handling of colored textures (#3844, #3868) 2021-03-03 18:34:07 +01:00
25679a411e Window, Nav: Fixed crash when calling SetWindowFocus(NULL) as the time a new window appears. (#3865) 2021-03-02 18:23:08 +01:00
4537d98d46 Backends: DX9: Fix to support colored glyphs, using newly introduced 'TexPixelsUseColors' info. (#3369, #3844) 2021-03-02 15:04:34 +01:00
eb57484935 Backends: DX9: add missing IMGUI_USE_BGRA_PACKED_COLOR support. Remove dinput.h headers. (#3844) 2021-03-02 15:04:34 +01:00
23ab4978e4 ImFontAtlas: Added 'bool TexPixelsUseColors' output to help backend decide of underlying texture format. (#3369, #3844) 2021-03-02 15:04:34 +01:00
cdf1926f21 Fix a typo in the demo text (#3840) 2021-02-25 13:33:47 +01:00
5aaab7424f Update FAQ.md 2021-02-25 13:10:02 +01:00
760c394707 Added links to Discussions. Closed Discord, yeah! (#2748) 2021-02-25 00:47:37 +01:00
3776ba565f Internals: TabBar: minor tweaks and renaming. 2021-02-24 19:40:15 +01:00
6f4b9c65ae Added commentary about DLL boundaries. Added GetAllocatorFunctions(). Tidying up. (#3836) 2021-02-24 19:38:39 +01:00
3f5bb5939a Examples: Fix MinGW detection in makefiles. Fix example_null build due to missing IME input libs. (#2590) 2021-02-24 17:18:53 +01:00
9b32f7bf2d Fix example_null Makefile for Mingw (#2590) 2021-02-22 14:44:06 +01:00
edf135c18d Win32+MinGW: Re-enabled IME functions by default even under MinGW. (#2590, #738) 2021-02-22 14:39:44 +01:00
ece854564a Log/Capture: Added LogTextV, a va_list variant of LogText. (#3828) 2021-02-22 11:58:51 +01:00
a8f76c23a4 Window: Shrink close button hit-testing region when it covers an abnormally high portion of the window visible area (e.g. when window is collapsed and moved in a corner)to facilitate moving the window away. (#3825) 2021-02-18 17:23:10 +01:00
0ecdf8167c DragScalar: Fixed crash when using DragScalar() directly with ImGuiSliderFlags_AlwaysClamp + only one of either p_min or p_max set. (#3824) [@harry75369] 2021-02-18 16:12:41 +01:00
c154629152 Backends: Win32: Added ImGui_ImplWin32_EnableAlphaCompositing() helper. (#2766, #3447)
Pragma linking with dwmapi.lib (Vista-era, ~9 kb). MinGW users will need to link with -ldwmapi.
2021-02-18 16:04:11 +01:00
6a161b8789 Examples: Reworked setup of clear color to be compatible with transparent values. (#2693, #2764, #2766, #2873, #3447, #3813, #3816) 2021-02-18 11:38:41 +01:00
bda12e5fdd Backends: Rework blending equation to preserve alpha in output buffer accross all backends. (#2693, #2764, #2766, #2873, #3447, #3813, #3816)
Some of the viewport ideas from #2766 are not in there yet (e.g. Vulkan: setting compositeAlpha based on cap.supportedCompositeAlpha)
2021-02-18 11:38:41 +01:00
27a5bdb916 Backends: Win32: Fixed ImGui_ImplWin32_EnableDpiAwareness() attempting to get SetProcessDpiAwareness from shcore.dll on Windows 8 whereas it is only supported on Windows 8.1.
+ Added other helpers for reference (unused currently, other features will want them)
2021-02-17 19:41:41 +01:00
fb15d8c858 Improve on automatic circle segment count calculation. (#3808) Amends 2021-02-17 14:22:31 +01:00
f107693d9b Improve on automatic circle segment count calculation. (#3808) 2021-02-17 12:55:39 +01:00
b47aa46d81 Tables: TableSetupColumn() user id uses ImGuiID as intended (typedef ImU32). internals: added GetCurrentTable(), LeftMostEnabledColumn. Demo/docs tweaks. 2021-02-17 12:18:22 +01:00
9576dfd5e7 CI: Use workflow_run to trigger scheduled builds and static analysis.
Scheduled builds now are triggered by a dummy "scheduled" workflow that is invoked by the timer. This gives forks an ability to disable scheduled builds while maintaining ability to perform CI builds in forked repository. Similarly static analysis is invoked on completion of "build" workflow, ensuring analysis is performed with every build. Also should build workflow triggers change, we do not need to replicate same changes in static analysis workflow file.
2021-02-16 14:39:16 +01:00
30b7545841 Version 1.82 WIP 2021-02-15 18:10:14 +01:00
61b19489f1 Made a change to CalcWindowSizeAfterConstraint() which MSVC optimizer seems to trip on. (read on)
We seldomly modify a local ImVec2 passed as parameter. This should be perfectly legal but libigl stumbled on a what may be a MSVC optimizer bug?
Only seven function in the codebase modify as 'ImVec2 parameter' but this is the only static one (and fairly small that is) which may tempt optimizer to perform optimizations over caller-callee boundaries?
While we can't explain it fully yet and I assume it may haunt us back someday. Might also be chain reaction from some unobvious UB but can't see it right now...
Link: https://github.com/libigl/libigl/issues/1669
2021-02-12 16:34:22 +01:00
4df57136e9 Version 1.81 2021-02-10 21:16:58 +01:00
647a308ad3 Backends: GLFW: Add ImGui_ImplGlfw_InitForOther() instead of ImGui_ImplGlfw_InitForWebGPU() so it can be used for e.g. DX11. (#3632)
Amend dff0044
2021-02-10 17:27:33 +01:00
f14042ca78 Viewports Added ImGui::GetMainViewport() as a way to get the bounds and work area of the host display. (#3789, #1542)
Viewports: Backport a few constructs from 'docking' branch.
Viewports: Added ImGuiViewportFlags_IsPlatformWindow, ImGuiViewportFlags_IsPlatformMonitor, ImGuiViewportFlags_OwnedByApp (none of them were in docking branch yet). ImGuiViewportFlags_IsPlatformMonitor is merely there to convey future intent, not yet used.
Reduce uses of io.DisplaySize.
MainMenuBar: Backport work area handling code from 'docking' branch.
Metrics: Backported "Viewports" debug visualizer from 'docking' branch.
Demo: Rework 'Examples->Fullscreen Window'.
Demo: 'Simple Overlay' demo now moves under main menu-bar (if any) using GetMainViewport()'s work area.
2021-02-10 16:09:53 +01:00
3b4d3a9b73 Simplify CI scripts (#3764)
* Deps paths through https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable
* Use heredocs for pasting source code
* Remove fetch-depth arg, it's the default
* Merge the `brew install`s, it's simpler and maybe even faster
2021-02-10 16:08:46 +01:00
56f7bdae99 ImDrawList: Clarified PathArcTo() need for a_min <= a_max with an assert. Fixed PathArcToFast() handling of a_min > a_max. 2021-02-08 16:37:51 +01:00
03038df1cc ImDrawList: fix divide by zero (for which result was unused but triggering on some archs/setup) added by f144c67676 (#3738) 2021-02-08 14:03:24 +01:00
b898281e3c Demo: Added 'Examples->Fullscreen Window' demo. (#3789) + repack and zero-clear ImDrawData. 2021-02-05 15:44:10 +01:00
58a0a7058c Backends: Using SetTexID() consistently instead of assigning to ->TexID. May make the later obsolete eventually. 2021-02-03 18:30:26 +01:00
82a9b599ab Backend: webgpu: Fixes blending issue on Chrome 90+ and makes backend forward compatible with Emscripten 2.0.14 (#3632, #3770) 2021-02-03 16:35:11 +01:00
03d74a293d ListBox: renamed ListBoxHeader>BeginListBox, ListBoxFooter>EndListBox. Added demo bits. 2021-02-03 16:33:22 +01:00
6f6d4e0b70 ListBoxHeader: In version taking height in number of items, made vertical padding consistent regardless of if (items_count <= height_in_items) or not.
Demo: Tweaks.
2021-02-03 15:07:14 +01:00
e5cbf60def ListBox: tweaked default height calculation. simplifying code internally (rework passing of full rect). Should have no visible side-effects + misc comments. 2021-02-03 14:54:56 +01:00
90a518c501 Fixed typos (#3782) 2021-02-03 12:37:32 +01:00
d1a9efdd8f InputText: Fixed slightly off ScrollX tracking, noticeable with large values of FramePadding.x. Multiline: Fixed padding/cliprect not matching single-line version. (#3781)
Fixed FramePadding.y worth of vertical offset when aiming with mouse.
2021-02-02 16:30:57 +01:00
a3f0393351 Menus: Fixed an issue with child-menu auto-sizing (issue introduced by 6af92b0) (#3779) 2021-02-02 13:06:51 +01:00
929563c3a7 Log/Capture: Fixes for handling \n in strings. Improve the look of various widgets. Added LogSetNextTextDecoration helper. Fixup/amend dbaf74d75.
For now removed LogRenderedTextNewLine() - it is eventually desirable but currently carries too much ambiguities, so reverted until we have a better system and test suite.
2021-02-02 12:29:58 +01:00
dbaf74d758 Log/Capture: Fix various new line/spacing issue by using same render text position when there are both RenderText and LogRenderedText call in widget code.
Also Buttons are now enclosed in bracket
2021-02-02 09:38:57 +01:00
9d576a96a5 Tables: added internal TableSetColumnEnabled() helper. Comments. 2021-02-02 09:23:40 +01:00
4dec436161 SliderInt: Fixed click/drag when v_min==v_max from setting the value to zero. (#3774) 2021-02-01 17:34:16 +01:00
24be26e00e imgui_freetype: Add support for colored glyphs. Font: add support for untinted glyphs (#3369)
Amend 9499afd with missing static inline.
2021-02-01 16:32:26 +01:00
24aa6654df imgui_freetype: add support for colored glyphs with ImGuiFreeTypeBuilderFlags_LoadColor (#3369)
(squashed 4 commits)
2021-02-01 16:32:23 +01:00
4622fa4b66 Fonts: Fixed CalcTextSize() width rounding so it behaves more like a ceil. (#3776)
his is in order for text wrapping to have enough space when provided width precisely calculated with CalcTextSize().x. Amend 7b0bf230.
Note that the rounding of either positions and widths are technically undesirable (e.g. #3437, #791) but variety of code is currently on it so we are first fixing current behavior before we'll eventually change it.
2021-02-01 12:49:18 +01:00
9499afdf5e imgui_freetype: clarify breaking changes, and add BuildFontAtlas() to be consistent with planned obsolescence. Rename mislabelled internal helper. Demo: clarify labels in nested table demo. (#3765) 2021-01-28 20:53:53 +01:00
dff0044d4e Backends, Examples: Added support for WebGPU and corresponding example. Amend 5853fbd (#3632) 2021-01-28 15:40:31 +01:00
5853fbd68b Backends, Examples: Added support for WebGPU and corresponding example (#3632)
(Squashed 11 commits)
2021-01-28 11:37:46 +01:00
6487860aae Backends: Vulkan: Rework support for custom function/symbol loader (#3759, #3227), add ImGui_ImplVulkan_LoadFunctions (amend 6001c54)
Making it a separate function allows to use/test this with our examples or any code using the VulkanH helper called before ImGui_ImplVulkan_Init()
2021-01-27 13:43:49 +01:00
6001c54598 Backends: Vulkan: Support for custom function/symbol loader (#3759, #3227)
- It adds an optional feature to support dynamic linkage of Vulkan instead of using default linkage.
 - It is now possible to have several potentially working implementation and whenever the Vulkan library was available it can work.
2021-01-27 12:54:51 +01:00
066406b9be Backends: OSX: Fix mouse position not being reported when mouse buttons other than left one are down. (#3762)
# Conflicts:
#	docs/CHANGELOG.txt
2021-01-27 12:44:42 +01:00
e28b51786e Tables: Fixed PopItemWidth() or multi-components items not restoring per-colum ItemWidth correctly. (#3760) rework local stacks to facilitate modifying current value without altering the stack.
May consider doing the same for ItemFlags and moving to g.ItemFlags...
2021-01-27 12:35:57 +01:00
3867c6c5f0 Fonts: (Breaking) Rename ImGuiFreeType:: flags to ImGuiFreeTypeBuilderFlags_XXX. Remove ImGuiFreeType::BuildFontAtlas() flags. Rename ImFontConfig::RasterizerFlags to FontBuilderFlags. Add ImFontBuilderIO (opaque). Amend 53d59f3 with a dozen of small fixes. 2021-01-26 17:25:09 +01:00
9417acc20f Fonts: if IMGUI_ENABLE_FREETYPE, use library by default for font rasterization
Also renamed IMGUI_DISABLE_STB_TRUETYPE to IMGUI_ENABLE_STB_TRUETYPE
2021-01-26 17:23:11 +01:00
6b32d0ebc7 Fixed minor title bar text clipping issue when FramePadding is small/zero and there are no close button in the window. (#3731) 2021-01-26 16:07:41 +01:00
a8d2d8ee97 Fixed uninitialized variable, amend f3f2578. (#3753) 2021-01-26 15:26:41 +01:00
f3f2578e8f Internals: Added context hook removal support (#3580, #3626, #3753) 2021-01-26 15:24:01 +01:00
f139846750 Backends: Win32: dynamically load XInput library (amends) (#3646, #3645, #3248, #2716) 2021-01-25 16:30:44 +01:00
633d1033af Backends: Win32: dynamically load XInput library (#3646, #3645, #3248, #2716) 2021-01-25 16:30:44 +01:00
2ed47e5822 Version 1.81 WIP 2021-01-25 16:30:44 +01:00
695a4bd1a9 Backends: Metal: Fixed texture storage mode when building on Mac Catalyst. (#3748) 2021-01-25 15:11:43 +01:00
f144c67676 ImDrawList: fixed AddCircle, AddCircleFilled buffer read overflow with (rad > 0.0f && rad < 1.0f && num_segments == 0). (#3738)
Amend 051ce076. Maximum cached count becomes 63 instead of 64.
2021-01-25 14:59:09 +01:00
58075c4414 Version 1.80 2021-01-21 20:36:18 +01:00
5178c3ce21 Tables: added ImGuiTableFlags_NoHostExtendX instead of using outer_size.x == 0.0f. Changed default outer_size to (0.0f, 0.0f). (#3605) 2021-01-21 16:20:31 +01:00
3b409d2b68 BeginChild: half-fixed child window name longer than 255 conflicting, merely raised the limit by using our shared large buffer. Comments. 2021-01-21 12:36:47 +01:00
6737037743 Tab Bar: fix 0ea4408 (#3414) 2021-01-20 19:35:10 +01:00
74b3b7cf58 Added experimental io.ConfigDragClickToInputText feature to enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). (#3737)
+ Offset ImGuiTableColumnFlags values.
2021-01-20 19:18:03 +01:00
dc0f3d982c DragFloat, DragInt: very slightly increased mouse drag threshold + expressing it as a factor of default value + disabled experimental click-to-input on DragXXX functions. (#3737) 2021-01-20 18:36:21 +01:00
ae0d2dd614 Tables: rework submission of content size and ideal content size to outer window (now using IdealMaxPos introduced in 6af92b0).
See Tests suite "table_reported_size_outer".
2021-01-20 11:38:46 +01:00
f379dc28a3 ImBitArray: Rename ClearBits() to ClearAllBits() and add SetAllBits(). ImBitArraySetBitRange work on range [n..n2) instead of [n..n2] 2021-01-20 11:33:59 +01:00
3fef132f62 Tables: Clear scroll value when reactivating scroll. Assert when passing width/weight to TableSetupColumn() without an explicit sizing policy at either table or column label.
Clearing scroll was initially made desirable by tests exhibiting side effects but generally feels saner.
table->UserOuterSize is poorly used in this commit but will be by subsequent commits.
2021-01-19 21:55:28 +01:00
0ea4408fd4 Tab Bar: Requested ideal content size (for auto-fit) doesn't affect horizontal scrolling. Followup to afa01d8. (#3414)
+ minor Table rename
2021-01-15 22:52:47 +01:00
6af92b05bf Internals: Layout: maintain two content sizes, optionally writing to IdealMaxPos to distinguish used from ideal size, later is used for auto-fit. Unused in this commit, should be no-op. (#3414)
# Conflicts:
#	imgui.cpp
2021-01-15 22:52:42 +01:00
6470681d87 Use GitHub URL for Tracy Profiler. (#3721) 2021-01-15 22:39:27 +01:00
4d419d1211 Tables: fixed ColumnsAutoFitWidth for resizable fixed columns reporting ideal width. 2021-01-15 17:48:36 +01:00
3e712631da Tables: more moving of code in EndTable(), should have no side-effect. 2021-01-15 14:20:24 +01:00
626e3e2b3b Tables: fix reported inner-width for scrolling tables off by a small padding amount + moved code.
Makes not much difference for inner-scrolling but makes a difference when reported to outer-window.
2021-01-15 12:40:40 +01:00
3edfc042ff Tables: Internals: Renaming, tweaks preparing ahead for trickier changes (should be all no-op). 2021-01-15 11:11:16 +01:00
9e281c12a8 Tables: Fixed very small tables edge cases: inverted clip rect with freezing + scroll, missing borders. 2021-01-14 19:16:06 +01:00
b0db741770 Demo tweaks. Moved Tabs to Widgets section. Added to Tables demo. Increased version following 00b35c08. 2021-01-14 11:59:33 +01:00
00b35c081e Tables: (breaking) removed ImGuiTableColumnFlags_WidthAuto which now can be expressed as _Fixed + _NoResize. WidthRequest gets updated when RequestOutputMaskByIndex is set rather than Visible. 2021-01-13 18:42:02 +01:00
8cea3e3ed3 Tables: fixed border straying out of rect when using ImGuiTableFlags_NoBordersInBody with small height. 2021-01-13 12:24:55 +01:00
002ba1a69f Tables: comments, tweak. CollapsingHeader: comments. (#3715) 2021-01-13 10:07:59 +01:00
feaa7ea003 Examples: Emscripten: Amend ba636c5. (#3705) 2021-01-11 18:46:23 +01:00
0f14dd9781 Examples: Emscripten: Add 'make serve' helper, move output to web/ folder. (#3705) 2021-01-11 18:46:23 +01:00
31a2f0c164 Tables: fixed outer_width misreported to layout for use with SameLine when ScrollY is set but not ScrollX (#3704, #3414) 2021-01-11 11:31:50 +01:00
e485d451d1 Backends: DX12: improve Windows 7 compatibility (#3696)
- Attempt to load d3d12.dll from local D3D12On7 paths before falling back to System32
- Do not statically import D3D12SerializeRootSignature
2021-01-11 11:07:43 +01:00
36535514d5 Backends: DX12: Fix warning (#3706). Disable obsolete Tables enums, leave them commented out. Using _MSVC_LANG to enable offsetof() and static_assert() on VS2015.3+ 2021-01-11 10:54:52 +01:00
e18abe3619 Tables: (Breaking) Added ImGuiTableFlags_SizingFixedSame, ImGuiTableFlags_SizingStretchProp. Removed ImGuiTableFlags_SameWidths.
Simplified some code and clariffied that currently non-resizable = always revert to default (while waiting to untangle Fixed vs Auto and programmatic override not going through TableSetupColumn)
Whereas ImGuiTableFlags_SameWidths has some unusual handling of mixed Fixed/Stretch columns, we know treat them separately.
2021-01-08 18:40:52 +01:00
0e3ba37e6d Tables: Tidying up. Shuffle some columns fields to facilitate debugging + comments + demo tweaks + metrics highlight. 2021-01-08 18:32:18 +01:00
414f82254b Tables: (Breaking) rename ImGuiTableFlags_SizingPolicyFixed > ImGuiTableFlags_SizingFixedFit, ImGuiTableFlags_SizingPolicyStretch > ImGuiTableFlags_SizingStretchSame in prevision for new policies. 2021-01-08 18:10:55 +01:00
8b5f3798e0 Tables: Moved demo chunks. Made right-most non-resizable same-width column hidden to alleviate the issue where they are off by 1 pixel. 2021-01-07 17:11:18 +01:00
94a432275b ImDrawList: Internals: Add ability to scale anti-alias fringe. This enable users to keep geometry sharp while scaling vertex buffer content. 2021-01-05 16:34:11 +01:00
9bcf77eb81 Fixed using IsItemEdited() after Combo() not matching the return value from Combo(). (#2034) + fix some PVS warnings, fix typo, blanks.
Amend e28b1078
2021-01-04 19:15:20 +01:00
7d5d5711c2 Backends: OpenGL2, OpenGL3: Backup and restore GL_SHADE_MODAL, GL_STENCIL_TEST, clear GL_NORMAL_ARRAY. Comments., (#3671, #3668) 2021-01-03 17:01:54 +01:00
0a5f399805 Tables: Fix hiding column right after the frozen line. Fix hovering/resising column delimiter scrolled under frozen columns. (#3678) 2021-01-03 15:45:56 +01:00
1c1d3b7ab5 Added 64-bit variants of CheckboxFlags() in imgui_internal.h. Improve assert on mismatched ListBoxFooter() call. Fix FAQ index. (#3687) 2021-01-03 15:45:56 +01:00
8ec5daf35d Happy new year! 2021-01-03 15:42:32 +01:00
fa963b9aaf Inputs: Internal: added SetItemUsingMouseWheel() and mechanism to request mouse wheel for both HoveredId and ActiveId. (#2891)
Based on @kudaba PR.
2020-12-25 18:22:34 +01:00
eb88fee052 Tables: internal tidying up, calculate WidthAuto in first loop of layout + TableSetupColumn() with unspecified stretch weight leaves it at -1.0f (unset) rather than overrding default. Amend 3b3503e.
Both changes are intended to have no side-effects. Committed separately from upcoming commit for easier future bissecting.
Small demo fix.
2020-12-25 16:30:44 +01:00
68faa16e1d Tables: report auto-fit width in EndTable(), extracted TableGetColumnWidthAuto(). fix minor flickering with IsPreserveWidthAuto (which is a debug feature still), moved some code. 2020-12-25 15:52:42 +01:00
3573195112 Tables: (breaking) rename ImGuiTableFlags_ColumnsWidthStretch > ImGuiTableFlags_SizingPolicyStretch, ImGuiTableFlags_ColumnsWidthFixed > ImGuiTableFlags_SizingPolicyFixed in prevision for other policies. 2020-12-24 18:32:27 +01:00
b015ea93fd Style tweaks, disabled default window rounding by default, reduced size of resize grip, made less prominent, increased WindowBg alpha in classic style.
TestEngine: Fixed Checkbox() not reporting its checkable state when clipped.
2020-12-24 18:31:51 +01:00
3fbb928c9f Tables: explicit/custom width in TableSetupColumn() is reapplied when table or column becomes not resizable. Comments. 2020-12-23 12:14:55 +01:00
956435768f Tables: (breaking) renamed ImGuiTableColumnFlags_WidthAutoResize to _WidthAuto., default to WidthFixed policy when host window has auto-resize.
Fix edge case with TableSetColumnWidth on small windows (amend 972ca816)
2020-12-23 11:39:15 +01:00
d497f112e7 Tables: simplified and tidying up TableSetColumnWidth(), fixes resizing a fixed column surrounded by stretch column (manually or via auto-fit menu). TableHeader() showing highlighted when held. 2020-12-22 17:13:11 +01:00
972ca8166f Tables: extracted code for TableGetMaxColumnWidth(), fixing "stuck" resize being lossy as it used an older calculation for it and didn't honor e.g. _NoKeepColumnsVisible 2020-12-22 16:40:52 +01:00
1aa59f90d0 Minor API comments and tweaks, standardize index used in imgui.h. Tables: tweaked TableSetupColumn() assert to use IM_ASSERT_USER_ERROR(). 2020-12-22 15:30:26 +01:00
2e48c2da81 Removed redirecting functions/enums names that were marked obsolete in 1.63 (August 2018) + tables tweaks. 2020-12-21 19:42:37 +01:00
4d8e839ddf Renamed ImDrawList::AddBezierCurve() to ImDrawList::AddBezierCubic(), ImDrawList::PathBezierCurveTo() to ImDrawList::PathBezierCubicCurveTo(). (#3127, #3664, #3665)
Renamed corresponding internal functions as well.
2020-12-21 17:13:36 +01:00
550bfcfc59 Amend defce31 Add ImDrawList::AddQuadBezierCurve(), ImDrawList::PathQuadBezierCurveTo() (#3127, #3664, #3665) 2020-12-21 16:30:10 +01:00
defce31c2e Add ImDrawList::AddQuadBezierCurve(), ImDrawList::PathQuadBezierCurveTo() (#3127, #3664, #3665) 2020-12-21 16:25:14 +01:00
a640698123 Clipper: Fixed incorrect end-list positioning when using ImGuiListClipper with 1 item (bug in 1.79). (#3663) 2020-12-21 15:53:42 +01:00
ae63d56426 Tables: remove ImGuiTableFlags_NoHeadersWidth since it is so rarely used and can be specified on a per-column basis. 2020-12-18 19:03:47 +01:00
532aa5a69b Tables: (breaking) change outer_size.x default value to -FLT_MIN, make outer_size.x == 0.0f act as ImGuiTableFlags_NoHostExtendX (#3605, ad83976b) when no scrolling and no stretch column. Which is more consistent.
Demo: moved "Compact table" to "Padding" section, makes more sense. Tweaked demo.
2020-12-18 17:51:50 +01:00
22ace4438c Tables: clarify assumption that rendering of bg/borders in bg0/bg1 are cpu-clipped allowing frozen/unfrozen to share drawcmd + remove offset on outer borders of scrolling tables. 2020-12-18 14:33:16 +01:00
30468829c2 Tables: Internal: Maintain InnerRect to further clarify some code. Renamed Bg1 fields to Bg2 (used by Selectable) as the other handles Bg0+Bg1. 2020-12-18 14:32:51 +01:00
ad83976b35 Tables: Added ImGuiTableFlags_NoHostExtendX (#3605) marked as WIP, will probably rename.
Moved some code from BeginTable() to TableUpdateLayout() to late latch some of the required data.
2020-12-18 14:32:51 +01:00
c4dbab8f5e Tables: reset all width apply to hidden stretch columns. Comments. 2020-12-16 17:12:21 +01:00
1fb26d18c4 Tables: fixed seemingly unnecessarily copy of ImGuiTableColumnFlags_NoDirectResize_ which broken resizing from W3| in a F1 W3 F2 setup. Header only allow overlap on hover, not when active (amend f2df804f)
Otherwise TableUpdateBorders() tends to override mouse cursor.
2020-12-16 15:43:51 +01:00
892b48e2d6 Tables: Lock contents width while resizing down an horizontal scrolling table. Headers declare ideal width regardless of clipping. Misc comments. 2020-12-16 13:04:49 +01:00
bd899efbd0 Tables: fixed "resize to default" of multiple stretch column (added 3b3503e, broken 7a61f340).
Fixed a warning.
Storing RightMostStretchedColumn column for resizing code.
Avoid clearing RightMostEnabledColumn in BeginTable() so resizing code can potentially use it.
(Added regression tests for resize all to default imgui_dev)
2020-12-14 15:49:20 +01:00
f2df804fcc Tables: four small fixes.
Fixed last item flags leaking to disabled column, affecting IsItemHovered(). (#3651).
Validate and fix invalid DisplayOrder data from ini file.
Allow TableHeaderRows() to function will missing TableSetupColumn() calls.
Made TableHeader() use AllowItemOverlap mode to allow submit subsequent item in same cell, since it covers the whole cell area.
2020-12-13 19:57:19 +01:00
738606a294 Tables: added ImGuiTableFlags_SortTristate. Renamed ImGuiTableFlags_MultiSortable to ImGuiTableFlags_SortMulti. Removed now unused FlagsIn storage. 2020-12-11 23:01:09 +01:00
cad8935bfd Tables: revert setting colum cliprect.max.x to WorkMax.x instead of Max.x at it complicates header code. Fix clipped sort arrow. (amend 17536f9a) 2020-12-11 21:31:55 +01:00
bff1836922 Internals: added facility to hide windows from render without interfering with the HiddenFramesCanSkipItems/HiddenFramesCannotSkipItems fields which have effects on layout. Compact some fields.
Ideally we'd have a simpler system but it's not easy to make the capture system change to hook at the right spot. Will rework.
2020-12-11 14:37:58 +01:00
1ad5502f18 Tables: Closer to zero-clear constructor. Lazily clearing name offsets to avoid an iteration in BeginTable(). Removed unused TableSetColumnIsEnabled(), signature went faulty anyway. 2020-12-10 19:45:20 +01:00
76964a27ce Tables: moved TableNextRow(), TableBeginRow(), TableEndRow(), TableNextColumn(), TableBeginCell(), TableEndCell() to their own section. 2020-12-10 18:39:37 +01:00
e6b875c09b Tables: Ditch old columns flags/setting if not called again. Displaying right-most border when using _SameWidths. Moving Width-related functions to their own section.
Effectively removed the TableFixColumnFlags() in first loop of TableUpdateLayout() to replace it with similar one but only when column not declared. I think this should be the right thing.
2020-12-10 18:33:33 +01:00
3346544cf5 Examples: Fix batch files (amend b1a18d82, #3513), standardize them + DirectX12: Move ImGui::Render() call above the first barrier to clarify its lack of effect on the graphics pipe. 2020-12-09 18:28:02 +01:00
17536f9add Tables: more consistent use of CellPadding.x*2 and clip-rect on right-most side of non-bordered column + fix cellbg for standalone TableHeader call.
Using CellPadding.x on both sides when BorderV is off, generally most consistent and with default value (4,2) promotes at-glance visible spacing between non-bordered columns. Effectively double horizontal padding on non-bordered columns.
Made ClipRect.Max.x matches WorkMaxX which is where we'd like to go for windows themselves.
TableHeader() submit single cell bg color if not already submitted as a full header row.
Misc comments/docs updates.
2020-12-09 15:13:09 +01:00
141 changed files with 7924 additions and 12908 deletions

View File

@ -1,6 +1,8 @@
# See http://editorconfig.org to read about the EditorConfig format.
# - Automatically supported by VS2017+ and most common IDE or text editors.
# - For older VS2010 to VS2015, install https://marketplace.visualstudio.com/items?itemName=EditorConfigTeam.EditorConfig
# - In theory automatically supported by VS2017+ and most common IDE or text editors.
# - In practice VS2019 stills gets trailing whitespaces wrong :(
# - Suggest install to trim whitespaces: https://marketplace.visualstudio.com/items?itemName=MadsKristensen.TrailingWhitespaceVisualizer
# - Alternative for older VS2010 to VS2015: https://marketplace.visualstudio.com/items?itemName=EditorConfigTeam.EditorConfig
# top-most EditorConfig file
root = true

View File

@ -4,7 +4,7 @@
2. PLEASE CAREFULLY READ: [Issue Submitting Guidelines](https://github.com/ocornut/imgui/issues/2261)
3. FOR FIRST-TIME USERS ISSUES COMPILING/LINKING/RUNNING/LOADING FONTS, please use the [Discord server](http://discord.dearimgui.org).
3. FOR FIRST-TIME USERS ISSUES COMPILING/LINKING/RUNNING/LOADING FONTS, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions).
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 link provided in (1) (2).

View File

@ -1,10 +1,18 @@
name: build
on:
push: {}
pull_request: {}
schedule:
- cron: '0 9 * * *'
push:
pull_request:
workflow_run:
# Use a workflow as a trigger of scheduled builds. Forked repositories can disable scheduled builds by disabling
# "scheduled" workflow, while maintaining ability to perform local CI builds.
workflows:
- scheduled
branches:
- master
- docking
types:
- requested
jobs:
Windows:
@ -12,21 +20,19 @@ jobs:
env:
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\
# Until gh-actions allow us to use env variables inside other env variables (because we need %GITHUB_WORKSPACE%) we have to use relative path to imgui/examples/example_name directory.
SDL2_DIR: ..\..\SDL2-devel-2.0.10-VC\SDL2-2.0.10\
VULKAN_SDK: ..\..\vulkan-sdk-1.1.121.2\
steps:
- uses: actions/checkout@v1
with:
fetch-depth: 1
- uses: actions/checkout@v2
- name: Install Dependencies
shell: powershell
run: |
Invoke-WebRequest -Uri "https://www.libsdl.org/release/SDL2-devel-2.0.10-VC.zip" -OutFile "SDL2-devel-2.0.10-VC.zip"
Expand-Archive -Path SDL2-devel-2.0.10-VC.zip
echo "SDL2_DIR=$(pwd)\SDL2-devel-2.0.10-VC\SDL2-2.0.10\" >>${env:GITHUB_ENV}
Invoke-WebRequest -Uri "https://github.com/ocornut/imgui/files/3789205/vulkan-sdk-1.1.121.2.zip" -OutFile vulkan-sdk-1.1.121.2.zip
Expand-Archive -Path vulkan-sdk-1.1.121.2.zip
echo "VULKAN_SDK=$(pwd)\vulkan-sdk-1.1.121.2\" >>${env:GITHUB_ENV}
- name: Fix Projects
shell: powershell
@ -55,24 +61,33 @@ jobs:
- name: Build example_null (single file build)
shell: bash
run: |
echo '#define IMGUI_IMPLEMENTATION' > example_single_file.cpp
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
echo '#include "examples/example_null/main.cpp"' >> example_single_file.cpp
g++ -I. -Wall -Wformat -o example_single_file.exe example_single_file.cpp
cat > example_single_file.cpp <<'EOF'
#define IMGUI_IMPLEMENTATION
#include "misc/single_file/imgui_single_file.h"
#include "examples/example_null/main.cpp"
EOF
g++ -I. -Wall -Wformat -o example_single_file.exe example_single_file.cpp -limm32
- name: Build example_null (with IMGUI_DISABLE_WIN32_FUNCTIONS)
shell: bash
run: |
echo '#define IMGUI_DISABLE_WIN32_FUNCTIONS' > example_single_file.cpp
echo '#define IMGUI_IMPLEMENTATION' >> example_single_file.cpp
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
echo '#include "examples/example_null/main.cpp"' >> example_single_file.cpp
g++ -I. -Wall -Wformat -o example_single_file.exe example_single_file.cpp
cat > example_single_file.cpp <<'EOF'
#define IMGUI_DISABLE_WIN32_FUNCTIONS
#define IMGUI_IMPLEMENTATION
#include "misc/single_file/imgui_single_file.h"
#include "examples/example_null/main.cpp"
EOF
g++ -I. -Wall -Wformat -o example_single_file.exe example_single_file.cpp -limm32
- name: Build example_null (as DLL)
shell: cmd
run: |
call "%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat"
echo #ifdef _EXPORT > example_single_file.cpp
echo # define IMGUI_API __declspec(dllexport) >> example_single_file.cpp
echo #else >> example_single_file.cpp
@ -80,6 +95,7 @@ jobs:
echo #endif >> example_single_file.cpp
echo #define IMGUI_IMPLEMENTATION >> example_single_file.cpp
echo #include "misc/single_file/imgui_single_file.h" >> example_single_file.cpp
cl.exe /D_USRDLL /D_WINDLL /D_EXPORT /I. example_single_file.cpp /LD /FeImGui.dll /link
cl.exe /I. ImGui.lib /Feexample_null.exe examples/example_null/main.cpp
@ -90,22 +106,22 @@ jobs:
- name: Build Win32 example_glfw_opengl3
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj /p:Platform=Win32 /p:Configuration=Release'
if: github.event_name == 'schedule'
if: github.event_name == 'workflow_run'
- name: Build Win32 example_glfw_vulkan
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release'
if: github.event_name == 'schedule'
if: github.event_name == 'workflow_run'
- name: Build Win32 example_sdl_vulkan
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release'
if: github.event_name == 'schedule'
if: github.event_name == 'workflow_run'
- name: Build Win32 example_sdl_opengl2
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj /p:Platform=Win32 /p:Configuration=Release'
if: github.event_name == 'schedule'
if: github.event_name == 'workflow_run'
- name: Build Win32 example_sdl_opengl3
shell: cmd
@ -114,7 +130,7 @@ jobs:
- name: Build Win32 example_sdl_directx11
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_directx11/example_sdl_directx11.vcxproj /p:Platform=Win32 /p:Configuration=Release'
if: github.event_name == 'schedule'
if: github.event_name == 'workflow_run'
- name: Build Win32 example_win32_directx9
shell: cmd
@ -127,12 +143,12 @@ jobs:
- name: Build Win32 example_win32_directx11
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx11/example_win32_directx11.vcxproj /p:Platform=Win32 /p:Configuration=Release'
if: github.event_name == 'schedule'
if: github.event_name == 'workflow_run'
- name: Build x64 example_glfw_opengl2
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj /p:Platform=x64 /p:Configuration=Release'
if: github.event_name == 'schedule'
if: github.event_name == 'workflow_run'
- name: Build x64 example_glfw_opengl3
shell: cmd
@ -145,17 +161,17 @@ jobs:
- name: Build x64 example_sdl_vulkan
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release'
if: github.event_name == 'schedule'
if: github.event_name == 'workflow_run'
- name: Build x64 example_sdl_opengl2
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj /p:Platform=x64 /p:Configuration=Release'
if: github.event_name == 'schedule'
if: github.event_name == 'workflow_run'
- name: Build x64 example_sdl_opengl3
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release'
if: github.event_name == 'schedule'
if: github.event_name == 'workflow_run'
- name: Build x64 example_sdl_directx11
shell: cmd
@ -164,17 +180,17 @@ jobs:
- name: Build x64 example_win32_directx9
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx9/example_win32_directx9.vcxproj /p:Platform=x64 /p:Configuration=Release'
if: github.event_name == 'schedule'
if: github.event_name == 'workflow_run'
- name: Build x64 example_win32_directx10
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx10/example_win32_directx10.vcxproj /p:Platform=x64 /p:Configuration=Release'
if: github.event_name == 'schedule'
if: github.event_name == 'workflow_run'
- name: Build x64 example_win32_directx11
shell: cmd
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx11/example_win32_directx11.vcxproj /p:Platform=x64 /p:Configuration=Release'
if: github.event_name == 'schedule'
if: github.event_name == 'workflow_run'
- name: Build x64 example_win32_directx12
shell: cmd
@ -183,9 +199,7 @@ jobs:
Linux:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v1
with:
fetch-depth: 1
- uses: actions/checkout@v2
- name: Install Dependencies
run: |
@ -219,82 +233,118 @@ jobs:
- name: Build example_null (single file build)
run: |
echo '#define IMGUI_IMPLEMENTATION' > example_single_file.cpp
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
echo '#include "examples/example_null/main.cpp"' >> example_single_file.cpp
cat > example_single_file.cpp <<'EOF'
#define IMGUI_IMPLEMENTATION
#include "misc/single_file/imgui_single_file.h"
#include "examples/example_null/main.cpp"
EOF
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (with ImWchar32)
run: |
echo '#define IMGUI_USE_WCHAR32' > example_single_file.cpp
echo '#define IMGUI_IMPLEMENTATION' >> example_single_file.cpp
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
echo '#include "examples/example_null/main.cpp"' >> example_single_file.cpp
cat > example_single_file.cpp <<'EOF'
#define IMGUI_USE_WCHAR32
#define IMGUI_IMPLEMENTATION
#include "misc/single_file/imgui_single_file.h"
#include "examples/example_null/main.cpp"
EOF
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (with large ImDrawIdx)
run: |
echo '#define ImDrawIdx unsigned int' > example_single_file.cpp
echo '#define IMGUI_IMPLEMENTATION' >> example_single_file.cpp
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
echo '#include "examples/example_null/main.cpp"' >> example_single_file.cpp
cat > example_single_file.cpp <<'EOF'
#define ImDrawIdx unsigned int
#define IMGUI_IMPLEMENTATION
#include "misc/single_file/imgui_single_file.h"
#include "examples/example_null/main.cpp"
EOF
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (with IMGUI_DISABLE_OBSOLETE_FUNCTIONS)
run: |
echo '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' > example_single_file.cpp
echo '#define IMGUI_IMPLEMENTATION' >> example_single_file.cpp
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
echo '#include "examples/example_null/main.cpp"' >> example_single_file.cpp
cat > example_single_file.cpp <<'EOF'
#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
#define IMGUI_IMPLEMENTATION
#include "misc/single_file/imgui_single_file.h"
#include "examples/example_null/main.cpp"
EOF
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (with IMGUI_DISABLE_DEMO_WINDOWS and IMGUI_DISABLE_METRICS_WINDOW)
run: |
echo '#define IMGUI_DISABLE_DEMO_WINDOWS' > example_single_file.cpp
echo '#define IMGUI_DISABLE_METRICS_WINDOW' >> example_single_file.cpp
echo '#define IMGUI_IMPLEMENTATION' >> example_single_file.cpp
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
echo '#include "examples/example_null/main.cpp"' >> example_single_file.cpp
cat > example_single_file.cpp <<'EOF'
#define IMGUI_DISABLE_DEMO_WINDOWS
#define IMGUI_DISABLE_METRICS_WINDOW
#define IMGUI_IMPLEMENTATION
#include "misc/single_file/imgui_single_file.h"
#include "examples/example_null/main.cpp"
EOF
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (with IMGUI_DISABLE_FILE_FUNCTIONS)
run: |
echo '#define IMGUI_DISABLE_FILE_FUNCTIONS' > example_single_file.cpp
echo '#define IMGUI_IMPLEMENTATION' >> example_single_file.cpp
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
echo '#include "examples/example_null/main.cpp"' >> example_single_file.cpp
cat > example_single_file.cpp <<'EOF'
#define IMGUI_DISABLE_FILE_FUNCTIONS
#define IMGUI_IMPLEMENTATION
#include "misc/single_file/imgui_single_file.h"
#include "examples/example_null/main.cpp"
EOF
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (with IMGUI_USE_BGRA_PACKED_COLOR)
run: |
echo '#define IMGUI_USE_BGRA_PACKED_COLOR' > example_single_file.cpp
echo '#define IMGUI_IMPLEMENTATION' >> example_single_file.cpp
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
echo '#include "examples/example_null/main.cpp"' >> example_single_file.cpp
cat > example_single_file.cpp <<'EOF'
#define IMGUI_USE_BGRA_PACKED_COLOR
#define IMGUI_IMPLEMENTATION
#include "misc/single_file/imgui_single_file.h"
#include "examples/example_null/main.cpp"
EOF
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (with IM_VEC2_CLASS_EXTRA and IM_VEC4_CLASS_EXTRA)
run: |
echo 'struct MyVec2 { float x; float y; MyVec2(float x, float y) : x(x), y(y) { } };' > example_single_file.cpp
echo 'struct MyVec4 { float x; float y; float z; float w;' >> example_single_file.cpp
echo 'MyVec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) { } };' >> example_single_file.cpp
echo '#define IM_VEC2_CLASS_EXTRA \' >> example_single_file.cpp
echo ' ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \' >> example_single_file.cpp
echo ' operator MyVec2() const { return MyVec2(x, y); }' >> example_single_file.cpp
echo '#define IM_VEC4_CLASS_EXTRA \' >> example_single_file.cpp
echo ' ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \' >> example_single_file.cpp
echo ' operator MyVec4() const { return MyVec4(x, y, z, w); }' >> example_single_file.cpp
echo '#define IMGUI_IMPLEMENTATION' >> example_single_file.cpp
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
echo '#include "examples/example_null/main.cpp"' >> example_single_file.cpp
cat > example_single_file.cpp <<'EOF'
struct MyVec2 { float x; float y; MyVec2(float x, float y) : x(x), y(y) { } };
struct MyVec4 { float x; float y; float z; float w;
MyVec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) { } };
#define IM_VEC2_CLASS_EXTRA \
ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
operator MyVec2() const { return MyVec2(x, y); }
#define IM_VEC4_CLASS_EXTRA \
ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
operator MyVec4() const { return MyVec4(x, y, z, w); }
#define IMGUI_IMPLEMENTATION
#include "misc/single_file/imgui_single_file.h"
#include "examples/example_null/main.cpp"
EOF
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (without c++ runtime, Clang)
run: |
echo '#define IMGUI_IMPLEMENTATION' > example_single_file.cpp
echo '#define IMGUI_DISABLE_DEMO_WINDOWS' >> example_single_file.cpp
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
echo '#include "examples/example_null/main.cpp"' >> example_single_file.cpp
cat > example_single_file.cpp <<'EOF'
#define IMGUI_IMPLEMENTATION
#define IMGUI_DISABLE_DEMO_WINDOWS
#include "misc/single_file/imgui_single_file.h"
#include "examples/example_null/main.cpp"
EOF
clang++ -I. -Wall -Wformat -nodefaultlibs -fno-rtti -fno-exceptions -fno-threadsafe-statics -lc -lm -o example_single_file example_single_file.cpp
- name: Build example_glfw_opengl2
@ -302,42 +352,47 @@ jobs:
- name: Build example_glfw_opengl3
run: make -C examples/example_glfw_opengl3
if: github.event_name == 'schedule'
if: github.event_name == 'workflow_run'
- name: Build example_sdl_opengl2
run: make -C examples/example_sdl_opengl2
if: github.event_name == 'schedule'
if: github.event_name == 'workflow_run'
- name: Build example_sdl_opengl3
run: make -C examples/example_sdl_opengl3
MacOS:
runs-on: macOS-latest
runs-on: macos-latest
steps:
- uses: actions/checkout@v1
with:
fetch-depth: 1
- uses: actions/checkout@v2
- name: Install Dependencies
run: |
brew install glfw3
brew install sdl2
brew install glfw3 sdl2
- name: Build example_null (extra warnings, clang 64-bit)
run: make -C examples/example_null WITH_EXTRA_WARNINGS=1
- name: Build example_null (single file build)
run: |
echo '#define IMGUI_IMPLEMENTATION' > example_single_file.cpp
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
echo '#include "examples/example_null/main.cpp"' >> example_single_file.cpp
cat > example_single_file.cpp <<'EOF'
#define IMGUI_IMPLEMENTATION
#include "misc/single_file/imgui_single_file.h"
#include "examples/example_null/main.cpp"
EOF
clang++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (without c++ runtime)
run: |
echo '#define IMGUI_IMPLEMENTATION' > example_single_file.cpp
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
echo '#include "examples/example_null/main.cpp"' >> example_single_file.cpp
cat > example_single_file.cpp <<'EOF'
#define IMGUI_IMPLEMENTATION
#include "misc/single_file/imgui_single_file.h"
#include "examples/example_null/main.cpp"
EOF
clang++ -I. -Wall -Wformat -nodefaultlibs -fno-rtti -fno-exceptions -fno-threadsafe-statics -lc -lm -o example_single_file example_single_file.cpp
- name: Build example_glfw_opengl2
@ -345,7 +400,7 @@ jobs:
- name: Build example_glfw_opengl3
run: make -C examples/example_glfw_opengl3
if: github.event_name == 'schedule'
if: github.event_name == 'workflow_run'
- name: Build example_glfw_metal
run: make -C examples/example_glfw_metal
@ -355,7 +410,7 @@ jobs:
- name: Build example_sdl_opengl2
run: make -C examples/example_sdl_opengl2
if: github.event_name == 'schedule'
if: github.event_name == 'workflow_run'
- name: Build example_sdl_opengl3
run: make -C examples/example_sdl_opengl3
@ -367,11 +422,9 @@ jobs:
run: xcodebuild -project examples/example_apple_opengl2/example_apple_opengl2.xcodeproj -target example_osx_opengl2
iOS:
runs-on: macOS-latest
runs-on: macos-latest
steps:
- uses: actions/checkout@v1
with:
fetch-depth: 1
- uses: actions/checkout@v2
- name: Build example_apple_metal
run: |
@ -381,9 +434,7 @@ jobs:
Emscripten:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v1
with:
fetch-depth: 1
- uses: actions/checkout@v2
- name: Install Dependencies
run: |
@ -400,17 +451,34 @@ jobs:
popd
make -C examples/example_emscripten_opengl3
- name: Build example_emscripten_wgpu
run: |
pushd emsdk-master
source ./emsdk_env.sh
popd
make -C examples/example_emscripten_wgpu
Android:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: Build example_android_opengl3
run: |
cd examples/example_android_opengl3/android
gradle assembleDebug
Discord-CI:
runs-on: ubuntu-18.04
if: always()
needs: [Windows, Linux, MacOS, iOS, Emscripten]
needs: [Windows, Linux, MacOS, iOS, Emscripten, Android]
steps:
- uses: dearimgui/github_discord_notifier@latest
with:
discord-webhook: ${{ secrets.DISCORD_CI_WEBHOOK }}
github-token: ${{ github.token }}
action-task: discord-jobs
discord-filter: "'{{ github.branch }}'.match(/master|docking|tables/g) != null && '{{ run.conclusion }}' != '{{ last_run.conclusion }}'"
discord-filter: "'{{ github.branch }}'.match(/master|docking/g) != null && '{{ run.conclusion }}' != '{{ last_run.conclusion }}'"
discord-username: GitHub Actions
discord-job-new-failure-message: ''
discord-job-fixed-failure-message: ''

15
.github/workflows/scheduled.yml vendored Normal file
View File

@ -0,0 +1,15 @@
#
# This is a dummy workflow used to trigger scheduled builds. Forked repositories most likely should disable this
# workflow to avoid daily builds of inactive repositories.
#
name: scheduled
on:
schedule:
- cron: '0 9 * * *'
jobs:
scheduled:
runs-on: ubuntu-latest
steps:
- run: exit 0

View File

@ -1,8 +1,12 @@
name: static-analysis
on:
push: {}
pull_request: {}
workflow_run:
# Perform static analysis together with build workflow. Build triggers of "build" workflow do not need to be repeated here.
workflows:
- build
types:
- requested
jobs:
PVS-Studio:
@ -51,7 +55,7 @@ jobs:
discord-webhook: ${{ secrets.DISCORD_CI_WEBHOOK }}
github-token: ${{ github.token }}
action-task: discord-jobs
discord-filter: "'{{ github.branch }}'.match(/master|docking|tables/g) != null && '{{ run.conclusion }}' != '{{ last_run.conclusion }}'"
discord-filter: "'{{ github.branch }}'.match(/master|docking/g) != null && '{{ run.conclusion }}' != '{{ last_run.conclusion }}'"
discord-username: GitHub Actions
discord-job-new-failure-message: ''
discord-job-fixed-failure-message: ''

3
.gitignore vendored
View File

@ -34,7 +34,8 @@ xcuserdata
examples/*.o.tmp
examples/*.out.js
examples/*.out.wasm
examples/example_emscripten_opengl3/example_emscripten_opengl3.*
examples/example_emscripten_opengl3/web/*
examples/example_emscripten_wgpu/web/*
## JetBrains IDE artifacts
.idea

View File

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

View File

@ -15,6 +15,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-02-18: Change blending equation to preserve alpha in output buffer.
// 2020-08-10: Inputs: Fixed horizontal mouse wheel direction.
// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
@ -68,7 +69,7 @@ struct ImDrawVertAllegro
static void ImGui_ImplAllegro5_SetupRenderState(ImDrawData* draw_data)
{
// Setup blending
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
al_set_separate_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
// Setup orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right).
@ -206,7 +207,7 @@ bool ImGui_ImplAllegro5_CreateDeviceObjects()
return false;
// Store our identifier
io.Fonts->TexID = (void*)cloned_img;
io.Fonts->SetTexID((void*)cloned_img);
g_Texture = cloned_img;
// Create an invisible mouse cursor
@ -222,8 +223,9 @@ void ImGui_ImplAllegro5_InvalidateDeviceObjects()
{
if (g_Texture)
{
ImGuiIO& io = ImGui::GetIO();
io.Fonts->SetTexID(NULL);
al_destroy_bitmap(g_Texture);
ImGui::GetIO().Fonts->TexID = NULL;
g_Texture = NULL;
}
if (g_MouseCursorInvisible)

View File

@ -0,0 +1,187 @@
// dear imgui: Platform Binding for Android native app
// This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3)
// Implemented features:
// [X] Platform: Keyboard arrays indexed using AKEYCODE_* codes, e.g. ImGui::IsKeyPressed(AKEYCODE_SPACE).
// Missing features:
// [ ] Platform: Clipboard support.
// [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [ ] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
// Important:
// - FIXME: On-screen keyboard currently needs to be enabled by the application (see examples/ and issue #3446)
// - FIXME: Unicode character inputs needs to be passed by Dear ImGui by the application (see examples/ and issue #3446)
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
// https://github.com/ocornut/imgui
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-03-04: Initial version.
#include "imgui.h"
#include "imgui_impl_android.h"
#include <time.h>
#include <map>
#include <queue>
#include <android/native_window.h>
#include <android/input.h>
#include <android/keycodes.h>
#include <android/log.h>
// Android data
static double g_Time = 0.0;
static ANativeWindow* g_Window;
static char g_LogTag[] = "ImGuiExample";
static std::map<int32_t, std::queue<int32_t>> g_KeyEventQueues; // FIXME: Remove dependency on map and queue once we use upcoming input queue.
int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event)
{
ImGuiIO& io = ImGui::GetIO();
int32_t event_type = AInputEvent_getType(input_event);
switch (event_type)
{
case AINPUT_EVENT_TYPE_KEY:
{
int32_t event_key_code = AKeyEvent_getKeyCode(input_event);
int32_t event_action = AKeyEvent_getAction(input_event);
int32_t event_meta_state = AKeyEvent_getMetaState(input_event);
io.KeyCtrl = ((event_meta_state & AMETA_CTRL_ON) != 0);
io.KeyShift = ((event_meta_state & AMETA_SHIFT_ON) != 0);
io.KeyAlt = ((event_meta_state & AMETA_ALT_ON) != 0);
switch (event_action)
{
// FIXME: AKEY_EVENT_ACTION_DOWN and AKEY_EVENT_ACTION_UP occur at once as soon as a touch pointer
// goes up from a key. We use a simple key event queue/ and process one event per key per frame in
// ImGui_ImplAndroid_NewFrame()...or consider using IO queue, if suitable: https://github.com/ocornut/imgui/issues/2787
case AKEY_EVENT_ACTION_DOWN:
case AKEY_EVENT_ACTION_UP:
g_KeyEventQueues[event_key_code].push(event_action);
break;
default:
break;
}
break;
}
case AINPUT_EVENT_TYPE_MOTION:
{
int32_t event_action = AMotionEvent_getAction(input_event);
int32_t event_pointer_index = (event_action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
event_action &= AMOTION_EVENT_ACTION_MASK;
switch (event_action)
{
case AMOTION_EVENT_ACTION_DOWN:
case AMOTION_EVENT_ACTION_UP:
// Physical mouse buttons (and probably other physical devices) also invoke the actions AMOTION_EVENT_ACTION_DOWN/_UP,
// but we have to process them separately to identify the actual button pressed. This is done below via
// AMOTION_EVENT_ACTION_BUTTON_PRESS/_RELEASE. Here, we only process "FINGER" input (and "UNKNOWN", as a fallback).
if((AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_FINGER)
|| (AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_UNKNOWN))
{
io.MouseDown[0] = (event_action == AMOTION_EVENT_ACTION_DOWN) ? true : false;
io.MousePos = ImVec2(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
}
break;
case AMOTION_EVENT_ACTION_BUTTON_PRESS:
case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
{
int32_t button_state = AMotionEvent_getButtonState(input_event);
io.MouseDown[0] = (button_state & AMOTION_EVENT_BUTTON_PRIMARY) ? true : false;
io.MouseDown[1] = (button_state & AMOTION_EVENT_BUTTON_SECONDARY) ? true : false;
io.MouseDown[2] = (button_state & AMOTION_EVENT_BUTTON_TERTIARY) ? true : false;
}
break;
case AMOTION_EVENT_ACTION_HOVER_MOVE: // Hovering: Tool moves while NOT pressed (such as a physical mouse)
case AMOTION_EVENT_ACTION_MOVE: // Touch pointer moves while DOWN
io.MousePos = ImVec2(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
break;
case AMOTION_EVENT_ACTION_SCROLL:
io.MouseWheel = AMotionEvent_getAxisValue(input_event, AMOTION_EVENT_AXIS_VSCROLL, event_pointer_index);
io.MouseWheelH = AMotionEvent_getAxisValue(input_event, AMOTION_EVENT_AXIS_HSCROLL, event_pointer_index);
break;
default:
break;
}
}
return 1;
default:
break;
}
return 0;
}
bool ImGui_ImplAndroid_Init(ANativeWindow* window)
{
g_Window = window;
g_Time = 0.0;
// Setup backend capabilities flags
ImGuiIO& io = ImGui::GetIO();
io.BackendPlatformName = "imgui_impl_android";
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
io.KeyMap[ImGuiKey_Tab] = AKEYCODE_TAB;
io.KeyMap[ImGuiKey_LeftArrow] = AKEYCODE_DPAD_LEFT; // also covers physical keyboard arrow key
io.KeyMap[ImGuiKey_RightArrow] = AKEYCODE_DPAD_RIGHT; // also covers physical keyboard arrow key
io.KeyMap[ImGuiKey_UpArrow] = AKEYCODE_DPAD_UP; // also covers physical keyboard arrow key
io.KeyMap[ImGuiKey_DownArrow] = AKEYCODE_DPAD_DOWN; // also covers physical keyboard arrow key
io.KeyMap[ImGuiKey_PageUp] = AKEYCODE_PAGE_UP;
io.KeyMap[ImGuiKey_PageDown] = AKEYCODE_PAGE_DOWN;
io.KeyMap[ImGuiKey_Home] = AKEYCODE_MOVE_HOME;
io.KeyMap[ImGuiKey_End] = AKEYCODE_MOVE_END;
io.KeyMap[ImGuiKey_Insert] = AKEYCODE_INSERT;
io.KeyMap[ImGuiKey_Delete] = AKEYCODE_FORWARD_DEL;
io.KeyMap[ImGuiKey_Backspace] = AKEYCODE_DEL;
io.KeyMap[ImGuiKey_Space] = AKEYCODE_SPACE;
io.KeyMap[ImGuiKey_Enter] = AKEYCODE_ENTER;
io.KeyMap[ImGuiKey_Escape] = AKEYCODE_ESCAPE;
io.KeyMap[ImGuiKey_KeyPadEnter] = AKEYCODE_NUMPAD_ENTER;
io.KeyMap[ImGuiKey_A] = AKEYCODE_A;
io.KeyMap[ImGuiKey_C] = AKEYCODE_C;
io.KeyMap[ImGuiKey_V] = AKEYCODE_V;
io.KeyMap[ImGuiKey_X] = AKEYCODE_X;
io.KeyMap[ImGuiKey_Y] = AKEYCODE_Y;
io.KeyMap[ImGuiKey_Z] = AKEYCODE_Z;
return true;
}
void ImGui_ImplAndroid_Shutdown()
{
}
void ImGui_ImplAndroid_NewFrame()
{
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer backend. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame().");
// Process queued key events
// FIXME: This is a workaround for multiple key event actions occurring at once (see above) and can be removed once we use upcoming input queue.
for (auto& key_queue : g_KeyEventQueues)
{
if (key_queue.second.empty())
continue;
io.KeysDown[key_queue.first] = (key_queue.second.front() == AKEY_EVENT_ACTION_DOWN);
key_queue.second.pop();
}
// Setup display size (every frame to accommodate for window resizing)
int32_t window_width = ANativeWindow_getWidth(g_Window);
int32_t window_height = ANativeWindow_getHeight(g_Window);
int display_width = window_width;
int display_height = window_height;
io.DisplaySize = ImVec2((float)window_width, (float)window_height);
if (window_width > 0 && window_height > 0)
io.DisplayFramebufferScale = ImVec2((float)display_width / window_width, (float)display_height / window_height);
// Setup time step
struct timespec current_timespec;
clock_gettime(CLOCK_MONOTONIC, &current_timespec);
double current_time = (double)(current_timespec.tv_sec) + (current_timespec.tv_nsec / 1000000000.0);
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f);
g_Time = current_time;
}

View File

@ -0,0 +1,26 @@
// dear imgui: Platform Binding for Android native app
// This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3)
// Implemented features:
// [X] Platform: Keyboard arrays indexed using AKEYCODE_* codes, e.g. ImGui::IsKeyPressed(AKEYCODE_SPACE).
// Missing features:
// [ ] Platform: Clipboard support.
// [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [ ] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
// Important:
// - FIXME: On-screen keyboard currently needs to be enabled by the application (see examples/ and issue #3446)
// - FIXME: Unicode character inputs needs to be passed by Dear ImGui by the application (see examples/ and issue #3446)
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
// https://github.com/ocornut/imgui
#pragma once
struct ANativeWindow;
struct AInputEvent;
IMGUI_IMPL_API bool ImGui_ImplAndroid_Init(ANativeWindow* window);
IMGUI_IMPL_API int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event);
IMGUI_IMPL_API void ImGui_ImplAndroid_Shutdown();
IMGUI_IMPL_API void ImGui_ImplAndroid_NewFrame();

View File

@ -2,8 +2,7 @@
// This needs to be used along with a Platform Backend (e.g. Win32)
// Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
@ -12,7 +11,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2021-02-18: DirectX10: Change blending equation to preserve alpha in output buffer.
// 2019-07-21: DirectX10: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData().
// 2019-05-29: DirectX10: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: DirectX10: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
@ -59,10 +58,6 @@ struct VERTEX_CONSTANT_BUFFER
float mvp[4][4];
};
// Forward Declarations
static void ImGui_ImplDX10_InitPlatformInterface();
static void ImGui_ImplDX10_ShutdownPlatformInterface();
static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* ctx)
{
// Setup viewport
@ -311,7 +306,7 @@ static void ImGui_ImplDX10_CreateFontsTexture()
}
// Store our identifier
io.Fonts->TexID = (ImTextureID)g_pFontTextureView;
io.Fonts->SetTexID((ImTextureID)g_pFontTextureView);
// Create texture sampler
{
@ -445,8 +440,8 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
desc.SrcBlend = D3D10_BLEND_SRC_ALPHA;
desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
desc.BlendOp = D3D10_BLEND_OP_ADD;
desc.SrcBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
desc.DestBlendAlpha = D3D10_BLEND_ZERO;
desc.SrcBlendAlpha = D3D10_BLEND_ONE;
desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
@ -488,7 +483,7 @@ void ImGui_ImplDX10_InvalidateDeviceObjects()
return;
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
@ -507,7 +502,6 @@ bool ImGui_ImplDX10_Init(ID3D10Device* device)
ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = "imgui_impl_dx10";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
// Get factory from device
IDXGIDevice* pDXGIDevice = NULL;
@ -525,14 +519,11 @@ bool ImGui_ImplDX10_Init(ID3D10Device* device)
if (pDXGIAdapter) pDXGIAdapter->Release();
g_pd3dDevice->AddRef();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplDX10_InitPlatformInterface();
return true;
}
void ImGui_ImplDX10_Shutdown()
{
ImGui_ImplDX10_ShutdownPlatformInterface();
ImGui_ImplDX10_InvalidateDeviceObjects();
if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; }
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
@ -543,124 +534,3 @@ void ImGui_ImplDX10_NewFrame()
if (!g_pFontSampler)
ImGui_ImplDX10_CreateDeviceObjects();
}
//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------
// Helper structure we store in the void* RenderUserData field of each ImGuiViewport to easily retrieve our backend data.
struct ImGuiViewportDataDx10
{
IDXGISwapChain* SwapChain;
ID3D10RenderTargetView* RTView;
ImGuiViewportDataDx10() { SwapChain = NULL; RTView = NULL; }
~ImGuiViewportDataDx10() { IM_ASSERT(SwapChain == NULL && RTView == NULL); }
};
static void ImGui_ImplDX10_CreateWindow(ImGuiViewport* viewport)
{
ImGuiViewportDataDx10* data = IM_NEW(ImGuiViewportDataDx10)();
viewport->RendererUserData = data;
// PlatformHandleRaw should always be a HWND, whereas PlatformHandle might be a higher-level handle (e.g. GLFWWindow*, SDL_Window*).
// Some backends will leave PlatformHandleRaw NULL, in which case we assume PlatformHandle will contain the HWND.
HWND hwnd = viewport->PlatformHandleRaw ? (HWND)viewport->PlatformHandleRaw : (HWND)viewport->PlatformHandle;
IM_ASSERT(hwnd != 0);
// Create swap chain
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferDesc.Width = (UINT)viewport->Size.x;
sd.BufferDesc.Height = (UINT)viewport->Size.y;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = 1;
sd.OutputWindow = hwnd;
sd.Windowed = TRUE;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
sd.Flags = 0;
IM_ASSERT(data->SwapChain == NULL && data->RTView == NULL);
g_pFactory->CreateSwapChain(g_pd3dDevice, &sd, &data->SwapChain);
// Create the render target
if (data->SwapChain)
{
ID3D10Texture2D* pBackBuffer;
data->SwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &data->RTView);
pBackBuffer->Release();
}
}
static void ImGui_ImplDX10_DestroyWindow(ImGuiViewport* viewport)
{
// The main viewport (owned by the application) will always have RendererUserData == NULL here since we didn't create the data for it.
if (ImGuiViewportDataDx10* data = (ImGuiViewportDataDx10*)viewport->RendererUserData)
{
if (data->SwapChain)
data->SwapChain->Release();
data->SwapChain = NULL;
if (data->RTView)
data->RTView->Release();
data->RTView = NULL;
IM_DELETE(data);
}
viewport->RendererUserData = NULL;
}
static void ImGui_ImplDX10_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
{
ImGuiViewportDataDx10* data = (ImGuiViewportDataDx10*)viewport->RendererUserData;
if (data->RTView)
{
data->RTView->Release();
data->RTView = NULL;
}
if (data->SwapChain)
{
ID3D10Texture2D* pBackBuffer = NULL;
data->SwapChain->ResizeBuffers(0, (UINT)size.x, (UINT)size.y, DXGI_FORMAT_UNKNOWN, 0);
data->SwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
if (pBackBuffer == NULL) { fprintf(stderr, "ImGui_ImplDX10_SetWindowSize() failed creating buffers.\n"); return; }
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &data->RTView);
pBackBuffer->Release();
}
}
static void ImGui_ImplDX10_RenderViewport(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataDx10* data = (ImGuiViewportDataDx10*)viewport->RendererUserData;
ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
g_pd3dDevice->OMSetRenderTargets(1, &data->RTView, NULL);
if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear))
g_pd3dDevice->ClearRenderTargetView(data->RTView, (float*)&clear_color);
ImGui_ImplDX10_RenderDrawData(viewport->DrawData);
}
static void ImGui_ImplDX10_SwapBuffers(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataDx10* data = (ImGuiViewportDataDx10*)viewport->RendererUserData;
data->SwapChain->Present(0, 0); // Present without vsync
}
void ImGui_ImplDX10_InitPlatformInterface()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Renderer_CreateWindow = ImGui_ImplDX10_CreateWindow;
platform_io.Renderer_DestroyWindow = ImGui_ImplDX10_DestroyWindow;
platform_io.Renderer_SetWindowSize = ImGui_ImplDX10_SetWindowSize;
platform_io.Renderer_RenderWindow = ImGui_ImplDX10_RenderViewport;
platform_io.Renderer_SwapBuffers = ImGui_ImplDX10_SwapBuffers;
}
void ImGui_ImplDX10_ShutdownPlatformInterface()
{
ImGui::DestroyPlatformWindows();
}

View File

@ -2,8 +2,7 @@
// This needs to be used along with a Platform Backend (e.g. Win32)
// Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.

View File

@ -3,7 +3,6 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
@ -12,7 +11,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer.
// 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled).
// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore.
// 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
@ -60,10 +59,6 @@ struct VERTEX_CONSTANT_BUFFER
float mvp[4][4];
};
// Forward Declarations
static void ImGui_ImplDX11_InitPlatformInterface();
static void ImGui_ImplDX11_ShutdownPlatformInterface();
static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx)
{
// Setup viewport
@ -323,7 +318,7 @@ static void ImGui_ImplDX11_CreateFontsTexture()
}
// Store our identifier
io.Fonts->TexID = (ImTextureID)g_pFontTextureView;
io.Fonts->SetTexID((ImTextureID)g_pFontTextureView);
// Create texture sampler
{
@ -457,8 +452,8 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
@ -500,7 +495,7 @@ void ImGui_ImplDX11_InvalidateDeviceObjects()
return;
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
@ -519,7 +514,6 @@ bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_co
ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = "imgui_impl_dx11";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
// Get factory from device
IDXGIDevice* pDXGIDevice = NULL;
@ -539,15 +533,11 @@ bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_co
g_pd3dDevice->AddRef();
g_pd3dDeviceContext->AddRef();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplDX11_InitPlatformInterface();
return true;
}
void ImGui_ImplDX11_Shutdown()
{
ImGui_ImplDX11_ShutdownPlatformInterface();
ImGui_ImplDX11_InvalidateDeviceObjects();
if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; }
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
@ -559,123 +549,3 @@ void ImGui_ImplDX11_NewFrame()
if (!g_pFontSampler)
ImGui_ImplDX11_CreateDeviceObjects();
}
//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------
// Helper structure we store in the void* RenderUserData field of each ImGuiViewport to easily retrieve our backend data.
struct ImGuiViewportDataDx11
{
IDXGISwapChain* SwapChain;
ID3D11RenderTargetView* RTView;
ImGuiViewportDataDx11() { SwapChain = NULL; RTView = NULL; }
~ImGuiViewportDataDx11() { IM_ASSERT(SwapChain == NULL && RTView == NULL); }
};
static void ImGui_ImplDX11_CreateWindow(ImGuiViewport* viewport)
{
ImGuiViewportDataDx11* data = IM_NEW(ImGuiViewportDataDx11)();
viewport->RendererUserData = data;
// PlatformHandleRaw should always be a HWND, whereas PlatformHandle might be a higher-level handle (e.g. GLFWWindow*, SDL_Window*).
// Some backend will leave PlatformHandleRaw NULL, in which case we assume PlatformHandle will contain the HWND.
HWND hwnd = viewport->PlatformHandleRaw ? (HWND)viewport->PlatformHandleRaw : (HWND)viewport->PlatformHandle;
IM_ASSERT(hwnd != 0);
// Create swap chain
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferDesc.Width = (UINT)viewport->Size.x;
sd.BufferDesc.Height = (UINT)viewport->Size.y;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = 1;
sd.OutputWindow = hwnd;
sd.Windowed = TRUE;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
sd.Flags = 0;
IM_ASSERT(data->SwapChain == NULL && data->RTView == NULL);
g_pFactory->CreateSwapChain(g_pd3dDevice, &sd, &data->SwapChain);
// Create the render target
if (data->SwapChain)
{
ID3D11Texture2D* pBackBuffer;
data->SwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &data->RTView);
pBackBuffer->Release();
}
}
static void ImGui_ImplDX11_DestroyWindow(ImGuiViewport* viewport)
{
// The main viewport (owned by the application) will always have RendererUserData == NULL since we didn't create the data for it.
if (ImGuiViewportDataDx11* data = (ImGuiViewportDataDx11*)viewport->RendererUserData)
{
if (data->SwapChain)
data->SwapChain->Release();
data->SwapChain = NULL;
if (data->RTView)
data->RTView->Release();
data->RTView = NULL;
IM_DELETE(data);
}
viewport->RendererUserData = NULL;
}
static void ImGui_ImplDX11_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
{
ImGuiViewportDataDx11* data = (ImGuiViewportDataDx11*)viewport->RendererUserData;
if (data->RTView)
{
data->RTView->Release();
data->RTView = NULL;
}
if (data->SwapChain)
{
ID3D11Texture2D* pBackBuffer = NULL;
data->SwapChain->ResizeBuffers(0, (UINT)size.x, (UINT)size.y, DXGI_FORMAT_UNKNOWN, 0);
data->SwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
if (pBackBuffer == NULL) { fprintf(stderr, "ImGui_ImplDX11_SetWindowSize() failed creating buffers.\n"); return; }
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &data->RTView);
pBackBuffer->Release();
}
}
static void ImGui_ImplDX11_RenderWindow(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataDx11* data = (ImGuiViewportDataDx11*)viewport->RendererUserData;
ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
g_pd3dDeviceContext->OMSetRenderTargets(1, &data->RTView, NULL);
if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear))
g_pd3dDeviceContext->ClearRenderTargetView(data->RTView, (float*)&clear_color);
ImGui_ImplDX11_RenderDrawData(viewport->DrawData);
}
static void ImGui_ImplDX11_SwapBuffers(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataDx11* data = (ImGuiViewportDataDx11*)viewport->RendererUserData;
data->SwapChain->Present(0, 0); // Present without vsync
}
static void ImGui_ImplDX11_InitPlatformInterface()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Renderer_CreateWindow = ImGui_ImplDX11_CreateWindow;
platform_io.Renderer_DestroyWindow = ImGui_ImplDX11_DestroyWindow;
platform_io.Renderer_SetWindowSize = ImGui_ImplDX11_SetWindowSize;
platform_io.Renderer_RenderWindow = ImGui_ImplDX11_RenderWindow;
platform_io.Renderer_SwapBuffers = ImGui_ImplDX11_SwapBuffers;
}
static void ImGui_ImplDX11_ShutdownPlatformInterface()
{
ImGui::DestroyPlatformWindows();
}

View File

@ -3,7 +3,6 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.

View File

@ -3,13 +3,11 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// FIXME: The transition from removing a viewport and moving the window in an existing hosted viewport tends to flicker.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
// This define is done in the example .vcxproj file and need to be replicated in your app (by e.g. editing imconfig.h)
// This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
@ -17,7 +15,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2021-02-18: DirectX12: Change blending equation to preserve alpha in output buffer.
// 2021-01-11: DirectX12: Improve Windows 7 compatibility (for D3D12On7) by loading d3d12.dll dynamically.
// 2020-09-16: DirectX12: Avoid rendering calls with zero-sized scissor rectangle since it generates a validation layer warning.
// 2020-09-08: DirectX12: Clarified support for building on 32-bit systems by redefining ImTextureID.
// 2019-10-18: DirectX12: *BREAKING CHANGE* Added extra ID3D12DescriptorHeap parameter to ImGui_ImplDX12_Init() function.
@ -50,88 +49,17 @@ static DXGI_FORMAT g_RTVFormat = DXGI_FORMAT_UNKNOWN;
static ID3D12Resource* g_pFontTextureResource = NULL;
static D3D12_CPU_DESCRIPTOR_HANDLE g_hFontSrvCpuDescHandle = {};
static D3D12_GPU_DESCRIPTOR_HANDLE g_hFontSrvGpuDescHandle = {};
static ID3D12DescriptorHeap* g_pd3dSrvDescHeap = NULL;
static UINT g_numFramesInFlight = 0;
// Buffers used during the rendering of a frame
struct ImGui_ImplDX12_RenderBuffers
struct FrameResources
{
ID3D12Resource* IndexBuffer;
ID3D12Resource* VertexBuffer;
int IndexBufferSize;
int VertexBufferSize;
};
// Buffers used for secondary viewports created by the multi-viewports systems
struct ImGui_ImplDX12_FrameContext
{
ID3D12CommandAllocator* CommandAllocator;
ID3D12Resource* RenderTarget;
D3D12_CPU_DESCRIPTOR_HANDLE RenderTargetCpuDescriptors;
};
// Helper structure we store in the void* RendererUserData field of each ImGuiViewport to easily retrieve our backend data.
// Main viewport created by application will only use the Resources field.
// Secondary viewports created by this backend will use all the fields (including Window fields),
struct ImGuiViewportDataDx12
{
// Window
ID3D12CommandQueue* CommandQueue;
ID3D12GraphicsCommandList* CommandList;
ID3D12DescriptorHeap* RtvDescHeap;
IDXGISwapChain3* SwapChain;
ID3D12Fence* Fence;
UINT64 FenceSignaledValue;
HANDLE FenceEvent;
ImGui_ImplDX12_FrameContext* FrameCtx;
// Render buffers
UINT FrameIndex;
ImGui_ImplDX12_RenderBuffers* FrameRenderBuffers;
ImGuiViewportDataDx12()
{
CommandQueue = NULL;
CommandList = NULL;
RtvDescHeap = NULL;
SwapChain = NULL;
Fence = NULL;
FenceSignaledValue = 0;
FenceEvent = NULL;
FrameCtx = new ImGui_ImplDX12_FrameContext[g_numFramesInFlight];
FrameIndex = UINT_MAX;
FrameRenderBuffers = new ImGui_ImplDX12_RenderBuffers[g_numFramesInFlight];
for (UINT i = 0; i < g_numFramesInFlight; ++i)
{
FrameCtx[i].CommandAllocator = NULL;
FrameCtx[i].RenderTarget = NULL;
// Create buffers with a default size (they will later be grown as needed)
FrameRenderBuffers[i].IndexBuffer = NULL;
FrameRenderBuffers[i].VertexBuffer = NULL;
FrameRenderBuffers[i].VertexBufferSize = 5000;
FrameRenderBuffers[i].IndexBufferSize = 10000;
}
}
~ImGuiViewportDataDx12()
{
IM_ASSERT(CommandQueue == NULL && CommandList == NULL);
IM_ASSERT(RtvDescHeap == NULL);
IM_ASSERT(SwapChain == NULL);
IM_ASSERT(Fence == NULL);
IM_ASSERT(FenceEvent == NULL);
for (UINT i = 0; i < g_numFramesInFlight; ++i)
{
IM_ASSERT(FrameCtx[i].CommandAllocator == NULL && FrameCtx[i].RenderTarget == NULL);
IM_ASSERT(FrameRenderBuffers[i].IndexBuffer == NULL && FrameRenderBuffers[i].VertexBuffer == NULL);
}
delete[] FrameCtx; FrameCtx = NULL;
delete[] FrameRenderBuffers; FrameRenderBuffers = NULL;
}
};
static FrameResources* g_pFrameResources = NULL;
static UINT g_numFramesInFlight = 0;
static UINT g_frameIndex = UINT_MAX;
template<typename T>
static void SafeRelease(T*& res)
@ -141,23 +69,12 @@ static void SafeRelease(T*& res)
res = NULL;
}
static void ImGui_ImplDX12_DestroyRenderBuffers(ImGui_ImplDX12_RenderBuffers* render_buffers)
{
SafeRelease(render_buffers->IndexBuffer);
SafeRelease(render_buffers->VertexBuffer);
render_buffers->IndexBufferSize = render_buffers->VertexBufferSize = 0;
}
struct VERTEX_CONSTANT_BUFFER
{
float mvp[4][4];
};
// Forward Declarations
static void ImGui_ImplDX12_InitPlatformInterface();
static void ImGui_ImplDX12_ShutdownPlatformInterface();
static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx, ImGui_ImplDX12_RenderBuffers* fr)
static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx, FrameResources* fr)
{
// Setup orthographic projection matrix into our constant buffer
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right).
@ -219,9 +136,10 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
return;
ImGuiViewportDataDx12* render_data = (ImGuiViewportDataDx12*)draw_data->OwnerViewport->RendererUserData;
render_data->FrameIndex++;
ImGui_ImplDX12_RenderBuffers* fr = &render_data->FrameRenderBuffers[render_data->FrameIndex % g_numFramesInFlight];
// FIXME: I'm assuming that this only gets called once per frame!
// If not, we can't just re-allocate the IB or VB, we'll have to do a proper allocator.
g_frameIndex = g_frameIndex + 1;
FrameResources* fr = &g_pFrameResources[g_frameIndex % g_numFramesInFlight];
// Create and grow vertex/index buffers if needed
if (fr->VertexBuffer == NULL || fr->VertexBufferSize < draw_data->TotalVtxCount)
@ -478,7 +396,7 @@ static void ImGui_ImplDX12_CreateFontsTexture()
// Store our identifier
static_assert(sizeof(ImTextureID) >= sizeof(g_hFontSrvGpuDescHandle.ptr), "Can't pack descriptor handle into TexID, 32-bit not supported yet.");
io.Fonts->TexID = (ImTextureID)g_hFontSrvGpuDescHandle.ptr;
io.Fonts->SetTexID((ImTextureID)g_hFontSrvGpuDescHandle.ptr);
}
bool ImGui_ImplDX12_CreateDeviceObjects()
@ -536,8 +454,34 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS;
// Load d3d12.dll and D3D12SerializeRootSignature() function address dynamically to facilitate using with D3D12On7.
// See if any version of d3d12.dll is already loaded in the process. If so, give preference to that.
static HINSTANCE d3d12_dll = ::GetModuleHandleA("d3d12.dll");
if (d3d12_dll == NULL)
{
// Attempt to load d3d12.dll from local directories. This will only succeed if
// (1) the current OS is Windows 7, and
// (2) there exists a version of d3d12.dll for Windows 7 (D3D12On7) in one of the following directories.
// See https://github.com/ocornut/imgui/pull/3696 for details.
const char* localD3d12Paths[] = { ".\\d3d12.dll", ".\\d3d12on7\\d3d12.dll", ".\\12on7\\d3d12.dll" }; // A. current directory, B. used by some games, C. used in Microsoft D3D12On7 sample
for (int i = 0; i < IM_ARRAYSIZE(localD3d12Paths); i++)
if ((d3d12_dll = ::LoadLibraryA(localD3d12Paths[i])) != NULL)
break;
// If failed, we are on Windows >= 10.
if (d3d12_dll == NULL)
d3d12_dll = ::LoadLibraryA("d3d12.dll");
if (d3d12_dll == NULL)
return false;
}
PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignatureFn = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)::GetProcAddress(d3d12_dll, "D3D12SerializeRootSignature");
if (D3D12SerializeRootSignatureFn == NULL)
return false;
ID3DBlob* blob = NULL;
if (D3D12SerializeRootSignature(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, NULL) != S_OK)
if (D3D12SerializeRootSignatureFn(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, NULL) != S_OK)
return false;
g_pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&g_pRootSignature));
@ -642,8 +586,8 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
desc.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
desc.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
desc.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
desc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
desc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO;
desc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE;
desc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
desc.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
desc.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
}
@ -697,7 +641,14 @@ void ImGui_ImplDX12_InvalidateDeviceObjects()
SafeRelease(g_pFontTextureResource);
ImGuiIO& io = ImGui::GetIO();
io.Fonts->TexID = NULL; // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
io.Fonts->SetTexID(NULL); // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
for (UINT i = 0; i < g_numFramesInFlight; i++)
{
FrameResources* fr = &g_pFrameResources[i];
SafeRelease(fr->IndexBuffer);
SafeRelease(fr->VertexBuffer);
}
}
bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap,
@ -707,50 +658,39 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO
ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = "imgui_impl_dx12";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional) // FIXME-VIEWPORT: Actually unfinished..
g_pd3dDevice = device;
g_RTVFormat = rtv_format;
g_hFontSrvCpuDescHandle = font_srv_cpu_desc_handle;
g_hFontSrvGpuDescHandle = font_srv_gpu_desc_handle;
g_pFrameResources = new FrameResources[num_frames_in_flight];
g_numFramesInFlight = num_frames_in_flight;
g_pd3dSrvDescHeap = cbv_srv_heap;
g_frameIndex = UINT_MAX;
IM_UNUSED(cbv_srv_heap); // Unused in master branch (will be used by multi-viewports)
// Create a dummy ImGuiViewportDataDx12 holder for the main viewport,
// Since this is created and managed by the application, we will only use the ->Resources[] fields.
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
main_viewport->RendererUserData = IM_NEW(ImGuiViewportDataDx12)();
// Setup backend capabilities flags
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplDX12_InitPlatformInterface();
// Create buffers with a default size (they will later be grown as needed)
for (int i = 0; i < num_frames_in_flight; i++)
{
FrameResources* fr = &g_pFrameResources[i];
fr->IndexBuffer = NULL;
fr->VertexBuffer = NULL;
fr->IndexBufferSize = 10000;
fr->VertexBufferSize = 5000;
}
return true;
}
void ImGui_ImplDX12_Shutdown()
{
// Manually delete main viewport render resources in-case we haven't initialized for viewports
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
if (ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)main_viewport->RendererUserData)
{
// We could just call ImGui_ImplDX12_DestroyWindow(main_viewport) as a convenience but that would be misleading since we only use data->Resources[]
for (UINT i = 0; i < g_numFramesInFlight; i++)
ImGui_ImplDX12_DestroyRenderBuffers(&data->FrameRenderBuffers[i]);
IM_DELETE(data);
main_viewport->RendererUserData = NULL;
}
// Clean up windows and device objects
ImGui_ImplDX12_ShutdownPlatformInterface();
ImGui_ImplDX12_InvalidateDeviceObjects();
delete[] g_pFrameResources;
g_pFrameResources = NULL;
g_pd3dDevice = NULL;
g_hFontSrvCpuDescHandle.ptr = 0;
g_hFontSrvGpuDescHandle.ptr = 0;
g_numFramesInFlight = 0;
g_pd3dSrvDescHeap = NULL;
g_frameIndex = UINT_MAX;
}
void ImGui_ImplDX12_NewFrame()
@ -758,239 +698,3 @@ void ImGui_ImplDX12_NewFrame()
if (!g_pPipelineState)
ImGui_ImplDX12_CreateDeviceObjects();
}
//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------
static void ImGui_ImplDX12_CreateWindow(ImGuiViewport* viewport)
{
ImGuiViewportDataDx12* data = IM_NEW(ImGuiViewportDataDx12)();
viewport->RendererUserData = data;
// PlatformHandleRaw should always be a HWND, whereas PlatformHandle might be a higher-level handle (e.g. GLFWWindow*, SDL_Window*).
// Some backends will leave PlatformHandleRaw NULL, in which case we assume PlatformHandle will contain the HWND.
HWND hwnd = viewport->PlatformHandleRaw ? (HWND)viewport->PlatformHandleRaw : (HWND)viewport->PlatformHandle;
IM_ASSERT(hwnd != 0);
data->FrameIndex = UINT_MAX;
// Create command queue.
D3D12_COMMAND_QUEUE_DESC queue_desc = {};
queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
HRESULT res = S_OK;
res = g_pd3dDevice->CreateCommandQueue(&queue_desc, IID_PPV_ARGS(&data->CommandQueue));
IM_ASSERT(res == S_OK);
// Create command allocator.
for (UINT i = 0; i < g_numFramesInFlight; ++i)
{
res = g_pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&data->FrameCtx[i].CommandAllocator));
IM_ASSERT(res == S_OK);
}
// Create command list.
res = g_pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, data->FrameCtx[0].CommandAllocator, NULL, IID_PPV_ARGS(&data->CommandList));
IM_ASSERT(res == S_OK);
data->CommandList->Close();
// Create fence.
res = g_pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&data->Fence));
IM_ASSERT(res == S_OK);
data->FenceEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
IM_ASSERT(data->FenceEvent != NULL);
// Create swap chain
// FIXME-VIEWPORT: May want to copy/inherit swap chain settings from the user/application.
DXGI_SWAP_CHAIN_DESC1 sd1;
ZeroMemory(&sd1, sizeof(sd1));
sd1.BufferCount = g_numFramesInFlight;
sd1.Width = (UINT)viewport->Size.x;
sd1.Height = (UINT)viewport->Size.y;
sd1.Format = g_RTVFormat;
sd1.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd1.SampleDesc.Count = 1;
sd1.SampleDesc.Quality = 0;
sd1.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
sd1.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
sd1.Scaling = DXGI_SCALING_STRETCH;
sd1.Stereo = FALSE;
IDXGIFactory4* dxgi_factory = NULL;
res = ::CreateDXGIFactory1(IID_PPV_ARGS(&dxgi_factory));
IM_ASSERT(res == S_OK);
IDXGISwapChain1* swap_chain = NULL;
res = dxgi_factory->CreateSwapChainForHwnd(data->CommandQueue, hwnd, &sd1, NULL, NULL, &swap_chain);
IM_ASSERT(res == S_OK);
dxgi_factory->Release();
// Or swapChain.As(&mSwapChain)
IM_ASSERT(data->SwapChain == NULL);
swap_chain->QueryInterface(IID_PPV_ARGS(&data->SwapChain));
swap_chain->Release();
// Create the render targets
if (data->SwapChain)
{
D3D12_DESCRIPTOR_HEAP_DESC desc = {};
desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
desc.NumDescriptors = g_numFramesInFlight;
desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
desc.NodeMask = 1;
HRESULT hr = g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&data->RtvDescHeap));
IM_ASSERT(hr == S_OK);
SIZE_T rtv_descriptor_size = g_pd3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
D3D12_CPU_DESCRIPTOR_HANDLE rtv_handle = data->RtvDescHeap->GetCPUDescriptorHandleForHeapStart();
for (UINT i = 0; i < g_numFramesInFlight; i++)
{
data->FrameCtx[i].RenderTargetCpuDescriptors = rtv_handle;
rtv_handle.ptr += rtv_descriptor_size;
}
ID3D12Resource* back_buffer;
for (UINT i = 0; i < g_numFramesInFlight; i++)
{
IM_ASSERT(data->FrameCtx[i].RenderTarget == NULL);
data->SwapChain->GetBuffer(i, IID_PPV_ARGS(&back_buffer));
g_pd3dDevice->CreateRenderTargetView(back_buffer, NULL, data->FrameCtx[i].RenderTargetCpuDescriptors);
data->FrameCtx[i].RenderTarget = back_buffer;
}
}
for (UINT i = 0; i < g_numFramesInFlight; i++)
ImGui_ImplDX12_DestroyRenderBuffers(&data->FrameRenderBuffers[i]);
}
static void ImGui_WaitForPendingOperations(ImGuiViewportDataDx12* data)
{
HRESULT hr = S_FALSE;
if (data && data->CommandQueue && data->Fence && data->FenceEvent)
{
hr = data->CommandQueue->Signal(data->Fence, ++data->FenceSignaledValue);
IM_ASSERT(hr == S_OK);
::WaitForSingleObject(data->FenceEvent, 0); // Reset any forgotten waits
hr = data->Fence->SetEventOnCompletion(data->FenceSignaledValue, data->FenceEvent);
IM_ASSERT(hr == S_OK);
::WaitForSingleObject(data->FenceEvent, INFINITE);
}
}
static void ImGui_ImplDX12_DestroyWindow(ImGuiViewport* viewport)
{
// The main viewport (owned by the application) will always have RendererUserData == NULL since we didn't create the data for it.
if (ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData)
{
ImGui_WaitForPendingOperations(data);
SafeRelease(data->CommandQueue);
SafeRelease(data->CommandList);
SafeRelease(data->SwapChain);
SafeRelease(data->RtvDescHeap);
SafeRelease(data->Fence);
::CloseHandle(data->FenceEvent);
data->FenceEvent = NULL;
for (UINT i = 0; i < g_numFramesInFlight; i++)
{
SafeRelease(data->FrameCtx[i].RenderTarget);
SafeRelease(data->FrameCtx[i].CommandAllocator);
ImGui_ImplDX12_DestroyRenderBuffers(&data->FrameRenderBuffers[i]);
}
IM_DELETE(data);
}
viewport->RendererUserData = NULL;
}
static void ImGui_ImplDX12_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
{
ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData;
ImGui_WaitForPendingOperations(data);
for (UINT i = 0; i < g_numFramesInFlight; i++)
SafeRelease(data->FrameCtx[i].RenderTarget);
if (data->SwapChain)
{
ID3D12Resource* back_buffer = NULL;
data->SwapChain->ResizeBuffers(0, (UINT)size.x, (UINT)size.y, DXGI_FORMAT_UNKNOWN, 0);
for (UINT i = 0; i < g_numFramesInFlight; i++)
{
data->SwapChain->GetBuffer(i, IID_PPV_ARGS(&back_buffer));
g_pd3dDevice->CreateRenderTargetView(back_buffer, NULL, data->FrameCtx[i].RenderTargetCpuDescriptors);
data->FrameCtx[i].RenderTarget = back_buffer;
}
}
}
static void ImGui_ImplDX12_RenderWindow(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData;
ImGui_ImplDX12_FrameContext* frame_context = &data->FrameCtx[data->FrameIndex % g_numFramesInFlight];
UINT back_buffer_idx = data->SwapChain->GetCurrentBackBufferIndex();
const ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
D3D12_RESOURCE_BARRIER barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier.Transition.pResource = data->FrameCtx[back_buffer_idx].RenderTarget;
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
// Draw
ID3D12GraphicsCommandList* cmd_list = data->CommandList;
frame_context->CommandAllocator->Reset();
cmd_list->Reset(frame_context->CommandAllocator, NULL);
cmd_list->ResourceBarrier(1, &barrier);
cmd_list->OMSetRenderTargets(1, &data->FrameCtx[back_buffer_idx].RenderTargetCpuDescriptors, FALSE, NULL);
if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear))
cmd_list->ClearRenderTargetView(data->FrameCtx[back_buffer_idx].RenderTargetCpuDescriptors, (float*)&clear_color, 0, NULL);
cmd_list->SetDescriptorHeaps(1, &g_pd3dSrvDescHeap);
ImGui_ImplDX12_RenderDrawData(viewport->DrawData, cmd_list);
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
cmd_list->ResourceBarrier(1, &barrier);
cmd_list->Close();
data->CommandQueue->Wait(data->Fence, data->FenceSignaledValue);
data->CommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&cmd_list);
data->CommandQueue->Signal(data->Fence, ++data->FenceSignaledValue);
}
static void ImGui_ImplDX12_SwapBuffers(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData;
data->SwapChain->Present(0, 0);
while (data->Fence->GetCompletedValue() < data->FenceSignaledValue)
::SwitchToThread();
}
void ImGui_ImplDX12_InitPlatformInterface()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Renderer_CreateWindow = ImGui_ImplDX12_CreateWindow;
platform_io.Renderer_DestroyWindow = ImGui_ImplDX12_DestroyWindow;
platform_io.Renderer_SetWindowSize = ImGui_ImplDX12_SetWindowSize;
platform_io.Renderer_RenderWindow = ImGui_ImplDX12_RenderWindow;
platform_io.Renderer_SwapBuffers = ImGui_ImplDX12_SwapBuffers;
}
void ImGui_ImplDX12_ShutdownPlatformInterface()
{
ImGui::DestroyPlatformWindows();
}

View File

@ -3,12 +3,11 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
// This define is done in the example .vcxproj file and need to be replicated in your app (by e.g. editing imconfig.h)
// This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
@ -17,6 +16,11 @@
#pragma once
#include "imgui.h" // IMGUI_IMPL_API
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable: 4471) // a forward declaration of an unscoped enumeration must have an underlying type
#endif
enum DXGI_FORMAT;
struct ID3D12Device;
struct ID3D12DescriptorHeap;
@ -37,3 +41,8 @@ IMGUI_IMPL_API void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3
// Use if you want to reset your rendering device without losing Dear ImGui state.
IMGUI_IMPL_API void ImGui_ImplDX12_InvalidateDeviceObjects();
IMGUI_IMPL_API bool ImGui_ImplDX12_CreateDeviceObjects();
#ifdef _MSC_VER
#pragma warning (pop)
#endif

View File

@ -3,7 +3,6 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
@ -12,7 +11,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2021-03-03: DirectX9: Added support for IMGUI_USE_BGRA_PACKED_COLOR in user's imconfig file.
// 2021-02-18: DirectX9: Change blending equation to preserve alpha in output buffer.
// 2019-05-29: DirectX9: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: DirectX9: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2019-03-29: Misc: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects().
@ -29,8 +29,6 @@
// DirectX
#include <d3d9.h>
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
// DirectX data
static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
@ -47,11 +45,11 @@ struct CUSTOMVERTEX
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
// Forward Declarations
static void ImGui_ImplDX9_InitPlatformInterface();
static void ImGui_ImplDX9_ShutdownPlatformInterface();
static void ImGui_ImplDX9_CreateDeviceObjectsForPlatformWindows();
static void ImGui_ImplDX9_InvalidateDeviceObjectsForPlatformWindows();
#ifdef IMGUI_USE_BGRA_PACKED_COLOR
#define IMGUI_COL_TO_DX9_ARGB(_COL) (_COL)
#else
#define IMGUI_COL_TO_DX9_ARGB(_COL) (((_COL) & 0xFF00FF00) | (((_COL) & 0xFF0000) >> 16) | (((_COL) & 0xFF) << 16))
#endif
static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
{
@ -75,6 +73,9 @@ static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
g_pd3dDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
@ -144,7 +145,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection);
// Copy and convert all vertices into a single contiguous buffer, convert colors to DX9 default format.
// FIXME-OPT: This is a waste of resource, the ideal is to use imconfig.h and
// FIXME-OPT: This is a minor waste of resource, the ideal is to use imconfig.h and
// 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR
// 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
CUSTOMVERTEX* vtx_dst;
@ -162,7 +163,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
vtx_dst->pos[0] = vtx_src->pos.x;
vtx_dst->pos[1] = vtx_src->pos.y;
vtx_dst->pos[2] = 0.0f;
vtx_dst->col = (vtx_src->col & 0xFF00FF00) | ((vtx_src->col & 0xFF0000) >> 16) | ((vtx_src->col & 0xFF) << 16); // RGBA --> ARGB for DirectX9
vtx_dst->col = IMGUI_COL_TO_DX9_ARGB(vtx_src->col);
vtx_dst->uv[0] = vtx_src->uv.x;
vtx_dst->uv[1] = vtx_src->uv.y;
vtx_dst++;
@ -213,11 +214,6 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
global_vtx_offset += cmd_list->VtxBuffer.Size;
}
// When using multi-viewports, it appears that there's an odd logic in DirectX9 which prevent subsequent windows
// from rendering until the first window submits at least one draw call, even once. That's our workaround. (see #2560)
if (global_vtx_offset == 0)
g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 0, 0, 0);
// Restore the DX9 transform
g_pd3dDevice->SetTransform(D3DTS_WORLD, &last_world);
g_pd3dDevice->SetTransform(D3DTS_VIEW, &last_view);
@ -234,20 +230,14 @@ bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = "imgui_impl_dx9";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
g_pd3dDevice = device;
g_pd3dDevice->AddRef();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplDX9_InitPlatformInterface();
return true;
}
void ImGui_ImplDX9_Shutdown()
{
ImGui_ImplDX9_ShutdownPlatformInterface();
ImGui_ImplDX9_InvalidateDeviceObjects();
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
}
@ -260,6 +250,17 @@ static bool ImGui_ImplDX9_CreateFontsTexture()
int width, height, bytes_per_pixel;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel);
// Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices)
#ifndef IMGUI_USE_BGRA_PACKED_COLOR
if (io.Fonts->TexPixelsUseColors)
{
ImU32* dst_start = (ImU32*)ImGui::MemAlloc(width * height * bytes_per_pixel);
for (ImU32* src = (ImU32*)pixels, *dst = dst_start, *dst_end = dst_start + width * height; dst < dst_end; src++, dst++)
*dst = IMGUI_COL_TO_DX9_ARGB(*src);
pixels = (unsigned char*)dst_start;
}
#endif
// Upload texture to graphics system
g_FontTexture = NULL;
if (g_pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_FontTexture, NULL) < 0)
@ -272,7 +273,12 @@ static bool ImGui_ImplDX9_CreateFontsTexture()
g_FontTexture->UnlockRect(0);
// Store our identifier
io.Fonts->TexID = (ImTextureID)g_FontTexture;
io.Fonts->SetTexID((ImTextureID)g_FontTexture);
#ifndef IMGUI_USE_BGRA_PACKED_COLOR
if (io.Fonts->TexPixelsUseColors)
ImGui::MemFree(pixels);
#endif
return true;
}
@ -283,7 +289,6 @@ bool ImGui_ImplDX9_CreateDeviceObjects()
return false;
if (!ImGui_ImplDX9_CreateFontsTexture())
return false;
ImGui_ImplDX9_CreateDeviceObjectsForPlatformWindows();
return true;
}
@ -293,8 +298,7 @@ void ImGui_ImplDX9_InvalidateDeviceObjects()
return;
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
if (g_FontTexture) { g_FontTexture->Release(); g_FontTexture = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
ImGui_ImplDX9_InvalidateDeviceObjectsForPlatformWindows();
if (g_FontTexture) { g_FontTexture->Release(); g_FontTexture = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
}
void ImGui_ImplDX9_NewFrame()
@ -302,142 +306,3 @@ void ImGui_ImplDX9_NewFrame()
if (!g_FontTexture)
ImGui_ImplDX9_CreateDeviceObjects();
}
//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------
// Helper structure we store in the void* RenderUserData field of each ImGuiViewport to easily retrieve our backend data.
struct ImGuiViewportDataDx9
{
IDirect3DSwapChain9* SwapChain;
D3DPRESENT_PARAMETERS d3dpp;
ImGuiViewportDataDx9() { SwapChain = NULL; ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS)); }
~ImGuiViewportDataDx9() { IM_ASSERT(SwapChain == NULL); }
};
static void ImGui_ImplDX9_CreateWindow(ImGuiViewport* viewport)
{
ImGuiViewportDataDx9* data = IM_NEW(ImGuiViewportDataDx9)();
viewport->RendererUserData = data;
// PlatformHandleRaw should always be a HWND, whereas PlatformHandle might be a higher-level handle (e.g. GLFWWindow*, SDL_Window*).
// Some backends will leave PlatformHandleRaw NULL, in which case we assume PlatformHandle will contain the HWND.
HWND hwnd = viewport->PlatformHandleRaw ? (HWND)viewport->PlatformHandleRaw : (HWND)viewport->PlatformHandle;
IM_ASSERT(hwnd != 0);
ZeroMemory(&data->d3dpp, sizeof(D3DPRESENT_PARAMETERS));
data->d3dpp.Windowed = TRUE;
data->d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
data->d3dpp.BackBufferWidth = (UINT)viewport->Size.x;
data->d3dpp.BackBufferHeight = (UINT)viewport->Size.y;
data->d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
data->d3dpp.hDeviceWindow = hwnd;
data->d3dpp.EnableAutoDepthStencil = FALSE;
data->d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
data->d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // Present without vsync
HRESULT hr = g_pd3dDevice->CreateAdditionalSwapChain(&data->d3dpp, &data->SwapChain); IM_UNUSED(hr);
IM_ASSERT(hr == D3D_OK);
IM_ASSERT(data->SwapChain != NULL);
}
static void ImGui_ImplDX9_DestroyWindow(ImGuiViewport* viewport)
{
// The main viewport (owned by the application) will always have RendererUserData == NULL since we didn't create the data for it.
if (ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData)
{
if (data->SwapChain)
data->SwapChain->Release();
data->SwapChain = NULL;
ZeroMemory(&data->d3dpp, sizeof(D3DPRESENT_PARAMETERS));
IM_DELETE(data);
}
viewport->RendererUserData = NULL;
}
static void ImGui_ImplDX9_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
{
ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData;
if (data->SwapChain)
{
data->SwapChain->Release();
data->SwapChain = NULL;
data->d3dpp.BackBufferWidth = (UINT)size.x;
data->d3dpp.BackBufferHeight = (UINT)size.y;
HRESULT hr = g_pd3dDevice->CreateAdditionalSwapChain(&data->d3dpp, &data->SwapChain); IM_UNUSED(hr);
IM_ASSERT(hr == D3D_OK);
}
}
static void ImGui_ImplDX9_RenderWindow(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData;
ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
LPDIRECT3DSURFACE9 render_target = NULL;
LPDIRECT3DSURFACE9 last_render_target = NULL;
LPDIRECT3DSURFACE9 last_depth_stencil = NULL;
data->SwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &render_target);
g_pd3dDevice->GetRenderTarget(0, &last_render_target);
g_pd3dDevice->GetDepthStencilSurface(&last_depth_stencil);
g_pd3dDevice->SetRenderTarget(0, render_target);
g_pd3dDevice->SetDepthStencilSurface(NULL);
if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear))
{
D3DCOLOR clear_col_dx = D3DCOLOR_RGBA((int)(clear_color.x*255.0f), (int)(clear_color.y*255.0f), (int)(clear_color.z*255.0f), (int)(clear_color.w*255.0f));
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, clear_col_dx, 1.0f, 0);
}
ImGui_ImplDX9_RenderDrawData(viewport->DrawData);
// Restore render target
g_pd3dDevice->SetRenderTarget(0, last_render_target);
g_pd3dDevice->SetDepthStencilSurface(last_depth_stencil);
render_target->Release();
last_render_target->Release();
if (last_depth_stencil) last_depth_stencil->Release();
}
static void ImGui_ImplDX9_SwapBuffers(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData;
HRESULT hr = data->SwapChain->Present(NULL, NULL, data->d3dpp.hDeviceWindow, NULL, NULL);
// Let main application handle D3DERR_DEVICELOST by resetting the device.
IM_ASSERT(hr == D3D_OK || hr == D3DERR_DEVICELOST);
}
static void ImGui_ImplDX9_InitPlatformInterface()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Renderer_CreateWindow = ImGui_ImplDX9_CreateWindow;
platform_io.Renderer_DestroyWindow = ImGui_ImplDX9_DestroyWindow;
platform_io.Renderer_SetWindowSize = ImGui_ImplDX9_SetWindowSize;
platform_io.Renderer_RenderWindow = ImGui_ImplDX9_RenderWindow;
platform_io.Renderer_SwapBuffers = ImGui_ImplDX9_SwapBuffers;
}
static void ImGui_ImplDX9_ShutdownPlatformInterface()
{
ImGui::DestroyPlatformWindows();
}
static void ImGui_ImplDX9_CreateDeviceObjectsForPlatformWindows()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
for (int i = 1; i < platform_io.Viewports.Size; i++)
if (!platform_io.Viewports[i]->RendererUserData)
ImGui_ImplDX9_CreateWindow(platform_io.Viewports[i]);
}
static void ImGui_ImplDX9_InvalidateDeviceObjectsForPlatformWindows()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
for (int i = 1; i < platform_io.Viewports.Size; i++)
if (platform_io.Viewports[i]->RendererUserData)
ImGui_ImplDX9_DestroyWindow(platform_io.Viewports[i]);
}

View File

@ -3,7 +3,6 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.

View File

@ -1,17 +1,13 @@
// dear imgui: Platform Backend for GLFW
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan..)
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
// (Requires: GLFW 3.1+. Prefer GLFW 3.3+ for full feature support.)
// (Requires: GLFW 3.1+)
// Implemented features:
// [X] Platform: Clipboard support.
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
// [X] Platform: Keyboard arrays indexed using GLFW_KEY_* codes, e.g. ImGui::IsKeyPressed(GLFW_KEY_SPACE).
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// Issues:
// [ ] Platform: Multi-viewport support: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
@ -19,7 +15,6 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2020-01-17: Inputs: Disable error callback while assigning mouse cursors because some X11 setup don't have them and it generates errors.
// 2019-12-05: Inputs: Added support for new mouse cursors added in GLFW 3.4+ (resizing cursors, not allowed cursor).
// 2019-10-18: Misc: Previously installed user callbacks are now restored on shutdown.
@ -57,20 +52,11 @@
#define GLFW_HAS_WINDOW_ALPHA (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwSetWindowOpacity
#define GLFW_HAS_PER_MONITOR_DPI (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwGetMonitorContentScale
#define GLFW_HAS_VULKAN (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ glfwCreateWindowSurface
#define GLFW_HAS_FOCUS_WINDOW (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ glfwFocusWindow
#define GLFW_HAS_FOCUS_ON_SHOW (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ GLFW_FOCUS_ON_SHOW
#define GLFW_HAS_MONITOR_WORK_AREA (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwGetMonitorWorkarea
#define GLFW_HAS_OSX_WINDOW_POS_FIX (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 + GLFW_VERSION_REVISION * 10 >= 3310) // 3.3.1+ Fixed: Resizing window repositions it on MacOS #1553
#ifdef GLFW_RESIZE_NESW_CURSOR // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2019-11-29 (cursors defines) // FIXME: Remove when GLFW 3.4 is released?
#ifdef GLFW_RESIZE_NESW_CURSOR // let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2019-11-29 (cursors defines) // FIXME: Remove when GLFW 3.4 is released?
#define GLFW_HAS_NEW_CURSORS (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3400) // 3.4+ GLFW_RESIZE_ALL_CURSOR, GLFW_RESIZE_NESW_CURSOR, GLFW_RESIZE_NWSE_CURSOR, GLFW_NOT_ALLOWED_CURSOR
#else
#define GLFW_HAS_NEW_CURSORS (0)
#endif
#ifdef GLFW_MOUSE_PASSTHROUGH // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2020-07-17 (passthrough)
#define GLFW_HAS_MOUSE_PASSTHROUGH (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3400) // 3.4+ GLFW_MOUSE_PASSTHROUGH
#else
#define GLFW_HAS_MOUSE_PASSTHROUGH (0)
#endif
// Data
enum GlfwClientApi
@ -85,19 +71,12 @@ static double g_Time = 0.0;
static bool g_MouseJustPressed[ImGuiMouseButton_COUNT] = {};
static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};
static bool g_InstalledCallbacks = false;
static bool g_WantUpdateMonitors = true;
// Chain GLFW callbacks for main viewport: 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.
static GLFWmousebuttonfun g_PrevUserCallbackMousebutton = NULL;
static GLFWscrollfun g_PrevUserCallbackScroll = NULL;
static GLFWkeyfun g_PrevUserCallbackKey = NULL;
static GLFWcharfun g_PrevUserCallbackChar = NULL;
static GLFWmonitorfun g_PrevUserCallbackMonitor = NULL;
// Forward Declarations
static void ImGui_ImplGlfw_UpdateMonitors();
static void ImGui_ImplGlfw_InitPlatformInterface();
static void ImGui_ImplGlfw_ShutdownPlatformInterface();
static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
{
@ -111,7 +90,7 @@ static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text)
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
{
if (g_PrevUserCallbackMousebutton != NULL && window == g_Window)
if (g_PrevUserCallbackMousebutton != NULL)
g_PrevUserCallbackMousebutton(window, button, action, mods);
if (action == GLFW_PRESS && button >= 0 && button < IM_ARRAYSIZE(g_MouseJustPressed))
@ -120,7 +99,7 @@ void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int acti
void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
{
if (g_PrevUserCallbackScroll != NULL && window == g_Window)
if (g_PrevUserCallbackScroll != NULL)
g_PrevUserCallbackScroll(window, xoffset, yoffset);
ImGuiIO& io = ImGui::GetIO();
@ -130,7 +109,7 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo
void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (g_PrevUserCallbackKey != NULL && window == g_Window)
if (g_PrevUserCallbackKey != NULL)
g_PrevUserCallbackKey(window, key, scancode, action, mods);
ImGuiIO& io = ImGui::GetIO();
@ -152,18 +131,13 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int a
void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c)
{
if (g_PrevUserCallbackChar != NULL && window == g_Window)
if (g_PrevUserCallbackChar != NULL)
g_PrevUserCallbackChar(window, c);
ImGuiIO& io = ImGui::GetIO();
io.AddInputCharacter(c);
}
void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int)
{
g_WantUpdateMonitors = true;
}
static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api)
{
g_Window = window;
@ -173,13 +147,9 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
#if GLFW_HAS_MOUSE_PASSTHROUGH || (GLFW_HAS_WINDOW_HOVERED && defined(_WIN32))
io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can set io.MouseHoveredViewport correctly (optional, not easy)
#endif
io.BackendPlatformName = "imgui_impl_glfw";
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB;
io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
@ -206,6 +176,9 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
io.ClipboardUserData = g_Window;
#if defined(_WIN32)
io.ImeWindowHandle = (void*)glfwGetWin32Window(g_Window);
#endif
// Create mouse cursors
// (By design, on X11 cursors are user configurable and some cursors may be missing. When a cursor doesn't exist,
@ -235,7 +208,6 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
g_PrevUserCallbackScroll = NULL;
g_PrevUserCallbackKey = NULL;
g_PrevUserCallbackChar = NULL;
g_PrevUserCallbackMonitor = NULL;
if (install_callbacks)
{
g_InstalledCallbacks = true;
@ -243,22 +215,8 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
g_PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback);
g_PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback);
g_PrevUserCallbackChar = glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback);
g_PrevUserCallbackMonitor = glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback);
}
// Update monitors the first time (note: monitor callback are broken in GLFW 3.2 and earlier, see github.com/glfw/glfw/issues/784)
ImGui_ImplGlfw_UpdateMonitors();
glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback);
// Our mouse update function expect PlatformHandle to be filled for the main viewport
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
main_viewport->PlatformHandle = (void*)g_Window;
#ifdef _WIN32
main_viewport->PlatformHandleRaw = glfwGetWin32Window(g_Window);
#endif
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplGlfw_InitPlatformInterface();
g_ClientApi = client_api;
return true;
}
@ -273,10 +231,13 @@ bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks)
return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_Vulkan);
}
bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks)
{
return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_Unknown);
}
void ImGui_ImplGlfw_Shutdown()
{
ImGui_ImplGlfw_ShutdownPlatformInterface();
if (g_InstalledCallbacks)
{
glfwSetMouseButtonCallback(g_Window, g_PrevUserCallbackMousebutton);
@ -308,62 +269,23 @@ static void ImGui_ImplGlfw_UpdateMousePosAndButtons()
// Update mouse position
const ImVec2 mouse_pos_backup = io.MousePos;
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
io.MouseHoveredViewport = 0;
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
for (int n = 0; n < platform_io.Viewports.Size; n++)
{
ImGuiViewport* viewport = platform_io.Viewports[n];
GLFWwindow* window = (GLFWwindow*)viewport->PlatformHandle;
IM_ASSERT(window != NULL);
#ifdef __EMSCRIPTEN__
const bool focused = true;
IM_ASSERT(platform_io.Viewports.Size == 1);
const bool focused = true; // Emscripten
#else
const bool focused = glfwGetWindowAttrib(window, GLFW_FOCUSED) != 0;
const bool focused = glfwGetWindowAttrib(g_Window, GLFW_FOCUSED) != 0;
#endif
if (focused)
if (focused)
{
if (io.WantSetMousePos)
{
if (io.WantSetMousePos)
{
glfwSetCursorPos(window, (double)(mouse_pos_backup.x - viewport->Pos.x), (double)(mouse_pos_backup.y - viewport->Pos.y));
}
else
{
double mouse_x, mouse_y;
glfwGetCursorPos(window, &mouse_x, &mouse_y);
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
// Multi-viewport mode: mouse position in OS absolute coordinates (io.MousePos is (0,0) when the mouse is on the upper-left of the primary monitor)
int window_x, window_y;
glfwGetWindowPos(window, &window_x, &window_y);
io.MousePos = ImVec2((float)mouse_x + window_x, (float)mouse_y + window_y);
}
else
{
// Single viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y);
}
}
for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
io.MouseDown[i] |= glfwGetMouseButton(window, i) != 0;
glfwSetCursorPos(g_Window, (double)mouse_pos_backup.x, (double)mouse_pos_backup.y);
}
else
{
double mouse_x, mouse_y;
glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y);
}
// (Optional) When using multiple viewports: set io.MouseHoveredViewport to the viewport the OS mouse cursor is hovering.
// Important: this information is not easy to provide and many high-level windowing library won't be able to provide it correctly, because
// - This is _ignoring_ viewports with the ImGuiViewportFlags_NoInputs flag (pass-through windows).
// - This is _regardless_ of whether another viewport is focused or being dragged from.
// If ImGuiBackendFlags_HasMouseHoveredViewport is not set by the backend, imgui will ignore this field and infer the information by relying on the
// rectangles and last focused time of every viewports it knows about. It will be unaware of other windows that may be sitting between or over your windows.
// [GLFW] FIXME: This is currently only correct on Win32. See what we do below with the WM_NCHITTEST, missing an equivalent for other systems.
// See https://github.com/glfw/glfw/issues/1236 if you want to help in making this a GLFW feature.
#if GLFW_HAS_MOUSE_PASSTHROUGH || (GLFW_HAS_WINDOW_HOVERED && defined(_WIN32))
const bool window_no_input = (viewport->Flags & ImGuiViewportFlags_NoInputs) != 0;
#if GLFW_HAS_MOUSE_PASSTHROUGH
glfwSetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH, window_no_input);
#endif
if (glfwGetWindowAttrib(window, GLFW_HOVERED) && !window_no_input)
io.MouseHoveredViewport = viewport->ID;
#endif
}
}
@ -374,22 +296,17 @@ static void ImGui_ImplGlfw_UpdateMouseCursor()
return;
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
for (int n = 0; n < platform_io.Viewports.Size; n++)
if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
{
GLFWwindow* window = (GLFWwindow*)platform_io.Viewports[n]->PlatformHandle;
if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
{
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
}
else
{
// Show OS mouse cursor
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
glfwSetCursor(window, g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
}
else
{
// Show OS mouse cursor
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
glfwSetCursor(g_Window, g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);
glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
}
@ -430,40 +347,6 @@ static void ImGui_ImplGlfw_UpdateGamepads()
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
}
static void ImGui_ImplGlfw_UpdateMonitors()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
int monitors_count = 0;
GLFWmonitor** glfw_monitors = glfwGetMonitors(&monitors_count);
platform_io.Monitors.resize(0);
for (int n = 0; n < monitors_count; n++)
{
ImGuiPlatformMonitor monitor;
int x, y;
glfwGetMonitorPos(glfw_monitors[n], &x, &y);
const GLFWvidmode* vid_mode = glfwGetVideoMode(glfw_monitors[n]);
monitor.MainPos = monitor.WorkPos = ImVec2((float)x, (float)y);
monitor.MainSize = monitor.WorkSize = ImVec2((float)vid_mode->width, (float)vid_mode->height);
#if GLFW_HAS_MONITOR_WORK_AREA
int w, h;
glfwGetMonitorWorkarea(glfw_monitors[n], &x, &y, &w, &h);
if (w > 0 && h > 0) // Workaround a small GLFW issue reporting zero on monitor changes: https://github.com/glfw/glfw/pull/1761
{
monitor.WorkPos = ImVec2((float)x, (float)y);
monitor.WorkSize = ImVec2((float)w, (float)h);
}
#endif
#if GLFW_HAS_PER_MONITOR_DPI
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.
float x_scale, y_scale;
glfwGetMonitorContentScale(glfw_monitors[n], &x_scale, &y_scale);
monitor.DpiScale = x_scale;
#endif
platform_io.Monitors.push_back(monitor);
}
g_WantUpdateMonitors = false;
}
void ImGui_ImplGlfw_NewFrame()
{
ImGuiIO& io = ImGui::GetIO();
@ -477,8 +360,6 @@ void ImGui_ImplGlfw_NewFrame()
io.DisplaySize = ImVec2((float)w, (float)h);
if (w > 0 && h > 0)
io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);
if (g_WantUpdateMonitors)
ImGui_ImplGlfw_UpdateMonitors();
// Setup time step
double current_time = glfwGetTime();
@ -491,368 +372,3 @@ void ImGui_ImplGlfw_NewFrame()
// Update game controllers (if enabled and available)
ImGui_ImplGlfw_UpdateGamepads();
}
//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------
// Helper structure we store in the void* RenderUserData field of each ImGuiViewport to easily retrieve our backend data.
struct ImGuiViewportDataGlfw
{
GLFWwindow* Window;
bool WindowOwned;
int IgnoreWindowPosEventFrame;
int IgnoreWindowSizeEventFrame;
ImGuiViewportDataGlfw() { Window = NULL; WindowOwned = false; IgnoreWindowSizeEventFrame = IgnoreWindowPosEventFrame = -1; }
~ImGuiViewportDataGlfw() { IM_ASSERT(Window == NULL); }
};
static void ImGui_ImplGlfw_WindowCloseCallback(GLFWwindow* window)
{
if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle(window))
viewport->PlatformRequestClose = true;
}
// GLFW may dispatch window pos/size events after calling glfwSetWindowPos()/glfwSetWindowSize().
// However: depending on the platform the callback may be invoked at different time:
// - on Windows it appears to be called within the glfwSetWindowPos()/glfwSetWindowSize() call
// - on Linux it is queued and invoked during glfwPollEvents()
// Because the event doesn't always fire on glfwSetWindowXXX() we use a frame counter tag to only
// ignore recent glfwSetWindowXXX() calls.
static void ImGui_ImplGlfw_WindowPosCallback(GLFWwindow* window, int, int)
{
if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle(window))
{
if (ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData)
{
bool ignore_event = (ImGui::GetFrameCount() <= data->IgnoreWindowPosEventFrame + 1);
//data->IgnoreWindowPosEventFrame = -1;
if (ignore_event)
return;
}
viewport->PlatformRequestMove = true;
}
}
static void ImGui_ImplGlfw_WindowSizeCallback(GLFWwindow* window, int, int)
{
if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle(window))
{
if (ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData)
{
bool ignore_event = (ImGui::GetFrameCount() <= data->IgnoreWindowSizeEventFrame + 1);
//data->IgnoreWindowSizeEventFrame = -1;
if (ignore_event)
return;
}
viewport->PlatformRequestResize = true;
}
}
static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
{
ImGuiViewportDataGlfw* data = IM_NEW(ImGuiViewportDataGlfw)();
viewport->PlatformUserData = data;
// GLFW 3.2 unfortunately always set focus on glfwCreateWindow() if GLFW_VISIBLE is set, regardless of GLFW_FOCUSED
// With GLFW 3.3, the hint GLFW_FOCUS_ON_SHOW fixes this problem
glfwWindowHint(GLFW_VISIBLE, false);
glfwWindowHint(GLFW_FOCUSED, false);
#if GLFW_HAS_FOCUS_ON_SHOW
glfwWindowHint(GLFW_FOCUS_ON_SHOW, false);
#endif
glfwWindowHint(GLFW_DECORATED, (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? false : true);
#if GLFW_HAS_WINDOW_TOPMOST
glfwWindowHint(GLFW_FLOATING, (viewport->Flags & ImGuiViewportFlags_TopMost) ? true : false);
#endif
GLFWwindow* share_window = (g_ClientApi == GlfwClientApi_OpenGL) ? g_Window : NULL;
data->Window = glfwCreateWindow((int)viewport->Size.x, (int)viewport->Size.y, "No Title Yet", NULL, share_window);
data->WindowOwned = true;
viewport->PlatformHandle = (void*)data->Window;
#ifdef _WIN32
viewport->PlatformHandleRaw = glfwGetWin32Window(data->Window);
#endif
glfwSetWindowPos(data->Window, (int)viewport->Pos.x, (int)viewport->Pos.y);
// Install GLFW callbacks for secondary viewports
glfwSetMouseButtonCallback(data->Window, ImGui_ImplGlfw_MouseButtonCallback);
glfwSetScrollCallback(data->Window, ImGui_ImplGlfw_ScrollCallback);
glfwSetKeyCallback(data->Window, ImGui_ImplGlfw_KeyCallback);
glfwSetCharCallback(data->Window, ImGui_ImplGlfw_CharCallback);
glfwSetWindowCloseCallback(data->Window, ImGui_ImplGlfw_WindowCloseCallback);
glfwSetWindowPosCallback(data->Window, ImGui_ImplGlfw_WindowPosCallback);
glfwSetWindowSizeCallback(data->Window, ImGui_ImplGlfw_WindowSizeCallback);
if (g_ClientApi == GlfwClientApi_OpenGL)
{
glfwMakeContextCurrent(data->Window);
glfwSwapInterval(0);
}
}
static void ImGui_ImplGlfw_DestroyWindow(ImGuiViewport* viewport)
{
if (ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData)
{
if (data->WindowOwned)
{
#if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED && defined(_WIN32)
HWND hwnd = (HWND)viewport->PlatformHandleRaw;
::RemovePropA(hwnd, "IMGUI_VIEWPORT");
#endif
glfwDestroyWindow(data->Window);
}
data->Window = NULL;
IM_DELETE(data);
}
viewport->PlatformUserData = viewport->PlatformHandle = NULL;
}
// We have submitted https://github.com/glfw/glfw/pull/1568 to allow GLFW to support "transparent inputs".
// In the meanwhile we implement custom per-platform workarounds here (FIXME-VIEWPORT: Implement same work-around for Linux/OSX!)
#if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED && defined(_WIN32)
static WNDPROC g_GlfwWndProc = NULL;
static LRESULT CALLBACK WndProcNoInputs(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_NCHITTEST)
{
// Let mouse pass-through the window. This will allow the backend to set io.MouseHoveredViewport properly (which is OPTIONAL).
// The ImGuiViewportFlags_NoInputs flag is set while dragging a viewport, as want to detect the window behind the one we are dragging.
// If you cannot easily access those viewport flags from your windowing/event code: you may manually synchronize its state e.g. in
// your main loop after calling UpdatePlatformWindows(). Iterate all viewports/platform windows and pass the flag to your windowing system.
ImGuiViewport* viewport = (ImGuiViewport*)::GetPropA(hWnd, "IMGUI_VIEWPORT");
if (viewport->Flags & ImGuiViewportFlags_NoInputs)
return HTTRANSPARENT;
}
return ::CallWindowProc(g_GlfwWndProc, hWnd, msg, wParam, lParam);
}
#endif
static void ImGui_ImplGlfw_ShowWindow(ImGuiViewport* viewport)
{
ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
#if defined(_WIN32)
// GLFW hack: Hide icon from task bar
HWND hwnd = (HWND)viewport->PlatformHandleRaw;
if (viewport->Flags & ImGuiViewportFlags_NoTaskBarIcon)
{
LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
ex_style &= ~WS_EX_APPWINDOW;
ex_style |= WS_EX_TOOLWINDOW;
::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style);
}
// GLFW hack: install hook for WM_NCHITTEST message handler
#if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED && defined(_WIN32)
::SetPropA(hwnd, "IMGUI_VIEWPORT", viewport);
if (g_GlfwWndProc == NULL)
g_GlfwWndProc = (WNDPROC)::GetWindowLongPtr(hwnd, GWLP_WNDPROC);
::SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)WndProcNoInputs);
#endif
#if !GLFW_HAS_FOCUS_ON_SHOW
// GLFW hack: GLFW 3.2 has a bug where glfwShowWindow() also activates/focus the window.
// The fix was pushed to GLFW repository on 2018/01/09 and should be included in GLFW 3.3 via a GLFW_FOCUS_ON_SHOW window attribute.
// See https://github.com/glfw/glfw/issues/1189
// FIXME-VIEWPORT: Implement same work-around for Linux/OSX in the meanwhile.
if (viewport->Flags & ImGuiViewportFlags_NoFocusOnAppearing)
{
::ShowWindow(hwnd, SW_SHOWNA);
return;
}
#endif
#endif
glfwShowWindow(data->Window);
}
static ImVec2 ImGui_ImplGlfw_GetWindowPos(ImGuiViewport* viewport)
{
ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
int x = 0, y = 0;
glfwGetWindowPos(data->Window, &x, &y);
return ImVec2((float)x, (float)y);
}
static void ImGui_ImplGlfw_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos)
{
ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
data->IgnoreWindowPosEventFrame = ImGui::GetFrameCount();
glfwSetWindowPos(data->Window, (int)pos.x, (int)pos.y);
}
static ImVec2 ImGui_ImplGlfw_GetWindowSize(ImGuiViewport* viewport)
{
ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
int w = 0, h = 0;
glfwGetWindowSize(data->Window, &w, &h);
return ImVec2((float)w, (float)h);
}
static void ImGui_ImplGlfw_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
{
ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
#if __APPLE__ && !GLFW_HAS_OSX_WINDOW_POS_FIX
// Native OS windows are positioned from the bottom-left corner on macOS, whereas on other platforms they are
// positioned from the upper-left corner. GLFW makes an effort to convert macOS style coordinates, however it
// doesn't handle it when changing size. We are manually moving the window in order for changes of size to be based
// on the upper-left corner.
int x, y, width, height;
glfwGetWindowPos(data->Window, &x, &y);
glfwGetWindowSize(data->Window, &width, &height);
glfwSetWindowPos(data->Window, x, y - height + size.y);
#endif
data->IgnoreWindowSizeEventFrame = ImGui::GetFrameCount();
glfwSetWindowSize(data->Window, (int)size.x, (int)size.y);
}
static void ImGui_ImplGlfw_SetWindowTitle(ImGuiViewport* viewport, const char* title)
{
ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
glfwSetWindowTitle(data->Window, title);
}
static void ImGui_ImplGlfw_SetWindowFocus(ImGuiViewport* viewport)
{
#if GLFW_HAS_FOCUS_WINDOW
ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
glfwFocusWindow(data->Window);
#else
// FIXME: What are the effect of not having this function? At the moment imgui doesn't actually call SetWindowFocus - we set that up ahead, will answer that question later.
(void)viewport;
#endif
}
static bool ImGui_ImplGlfw_GetWindowFocus(ImGuiViewport* viewport)
{
ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
return glfwGetWindowAttrib(data->Window, GLFW_FOCUSED) != 0;
}
static bool ImGui_ImplGlfw_GetWindowMinimized(ImGuiViewport* viewport)
{
ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
return glfwGetWindowAttrib(data->Window, GLFW_ICONIFIED) != 0;
}
#if GLFW_HAS_WINDOW_ALPHA
static void ImGui_ImplGlfw_SetWindowAlpha(ImGuiViewport* viewport, float alpha)
{
ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
glfwSetWindowOpacity(data->Window, alpha);
}
#endif
static void ImGui_ImplGlfw_RenderWindow(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
if (g_ClientApi == GlfwClientApi_OpenGL)
glfwMakeContextCurrent(data->Window);
}
static void ImGui_ImplGlfw_SwapBuffers(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
if (g_ClientApi == GlfwClientApi_OpenGL)
{
glfwMakeContextCurrent(data->Window);
glfwSwapBuffers(data->Window);
}
}
//--------------------------------------------------------------------------------------------------------
// IME (Input Method Editor) basic support for e.g. Asian language users
//--------------------------------------------------------------------------------------------------------
// We provide a Win32 implementation because this is such a common issue for IME users
#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(__GNUC__)
#define HAS_WIN32_IME 1
#include <imm.h>
#ifdef _MSC_VER
#pragma comment(lib, "imm32")
#endif
static void ImGui_ImplWin32_SetImeInputPos(ImGuiViewport* viewport, ImVec2 pos)
{
COMPOSITIONFORM cf = { CFS_FORCE_POSITION, { (LONG)(pos.x - viewport->Pos.x), (LONG)(pos.y - viewport->Pos.y) }, { 0, 0, 0, 0 } };
if (HWND hwnd = (HWND)viewport->PlatformHandleRaw)
if (HIMC himc = ::ImmGetContext(hwnd))
{
::ImmSetCompositionWindow(himc, &cf);
::ImmReleaseContext(hwnd, himc);
}
}
#else
#define HAS_WIN32_IME 0
#endif
//--------------------------------------------------------------------------------------------------------
// Vulkan support (the Vulkan renderer needs to call a platform-side support function to create the surface)
//--------------------------------------------------------------------------------------------------------
// Avoid including <vulkan.h> so we can build without it
#if GLFW_HAS_VULKAN
#ifndef VULKAN_H_
#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
#if defined(__LP64__) || defined(_WIN64) || defined(__x86_64__) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;
#else
#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
#endif
VK_DEFINE_HANDLE(VkInstance)
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR)
struct VkAllocationCallbacks;
enum VkResult { VK_RESULT_MAX_ENUM = 0x7FFFFFFF };
#endif // VULKAN_H_
extern "C" { extern GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); }
static int ImGui_ImplGlfw_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_instance, const void* vk_allocator, ImU64* out_vk_surface)
{
ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
IM_ASSERT(g_ClientApi == GlfwClientApi_Vulkan);
VkResult err = glfwCreateWindowSurface((VkInstance)vk_instance, data->Window, (const VkAllocationCallbacks*)vk_allocator, (VkSurfaceKHR*)out_vk_surface);
return (int)err;
}
#endif // GLFW_HAS_VULKAN
static void ImGui_ImplGlfw_InitPlatformInterface()
{
// Register platform interface (will be coupled with a renderer interface)
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Platform_CreateWindow = ImGui_ImplGlfw_CreateWindow;
platform_io.Platform_DestroyWindow = ImGui_ImplGlfw_DestroyWindow;
platform_io.Platform_ShowWindow = ImGui_ImplGlfw_ShowWindow;
platform_io.Platform_SetWindowPos = ImGui_ImplGlfw_SetWindowPos;
platform_io.Platform_GetWindowPos = ImGui_ImplGlfw_GetWindowPos;
platform_io.Platform_SetWindowSize = ImGui_ImplGlfw_SetWindowSize;
platform_io.Platform_GetWindowSize = ImGui_ImplGlfw_GetWindowSize;
platform_io.Platform_SetWindowFocus = ImGui_ImplGlfw_SetWindowFocus;
platform_io.Platform_GetWindowFocus = ImGui_ImplGlfw_GetWindowFocus;
platform_io.Platform_GetWindowMinimized = ImGui_ImplGlfw_GetWindowMinimized;
platform_io.Platform_SetWindowTitle = ImGui_ImplGlfw_SetWindowTitle;
platform_io.Platform_RenderWindow = ImGui_ImplGlfw_RenderWindow;
platform_io.Platform_SwapBuffers = ImGui_ImplGlfw_SwapBuffers;
#if GLFW_HAS_WINDOW_ALPHA
platform_io.Platform_SetWindowAlpha = ImGui_ImplGlfw_SetWindowAlpha;
#endif
#if GLFW_HAS_VULKAN
platform_io.Platform_CreateVkSurface = ImGui_ImplGlfw_CreateVkSurface;
#endif
#if HAS_WIN32_IME
platform_io.Platform_SetImeInputPos = ImGui_ImplWin32_SetImeInputPos;
#endif
// Register main window handle (which is owned by the main application, not by us)
// This is mostly for simplicity and consistency, so that our code (e.g. mouse handling etc.) can use same logic for main and secondary viewports.
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
ImGuiViewportDataGlfw* data = IM_NEW(ImGuiViewportDataGlfw)();
data->Window = g_Window;
data->WindowOwned = false;
main_viewport->PlatformUserData = data;
main_viewport->PlatformHandle = (void*)g_Window;
}
static void ImGui_ImplGlfw_ShutdownPlatformInterface()
{
}

View File

@ -1,5 +1,5 @@
// dear imgui: Platform Backend for GLFW
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan..)
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
// Implemented features:
@ -7,10 +7,6 @@
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [x] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: 3 cursors types are missing from GLFW.
// [X] Platform: Keyboard arrays indexed using GLFW_KEY_* codes, e.g. ImGui::IsKeyPressed(GLFW_KEY_SPACE).
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// Issues:
// [ ] Platform: Multi-viewport support: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
@ -24,10 +20,10 @@
#include "imgui.h" // IMGUI_IMPL_API
struct GLFWwindow;
struct GLFWmonitor;
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks);
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks);
IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown();
IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
@ -38,4 +34,3 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, i
IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);

View File

@ -1,8 +1,8 @@
// dear imgui: Platform Backend for GLUT/FreeGLUT
// This needs to be used along with a Renderer (e.g. OpenGL2)
// !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!!
// !!! If someone or something is teaching you GLUT in 2020, you are being abused. Please show some resistance. !!!
// !!! GLUT/FreeGLUT IS OBSOLETE PREHISTORIC SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!!
// !!! If someone or something is teaching you GLUT today, you are being abused. Please show some resistance. !!!
// !!! Nowadays, prefer using GLFW or SDL instead!
// Issues:

View File

@ -1,8 +1,8 @@
// dear imgui: Platform Backend for GLUT/FreeGLUT
// This needs to be used along with a Renderer (e.g. OpenGL2)
// !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!!
// !!! If someone or something is teaching you GLUT in 2020, you are being abused. Please show some resistance. !!!
// !!! GLUT/FreeGLUT IS OBSOLETE PREHISTORIC SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!!
// !!! If someone or something is teaching you GLUT today, you are being abused. Please show some resistance. !!!
// !!! Nowadays, prefer using GLFW or SDL instead!
// Issues:

View File

@ -194,7 +194,7 @@ bool ImGui_Marmalade_CreateDeviceObjects()
g_FontTexture->Upload();
// Store our identifier
io.Fonts->TexID = (ImTextureID)g_FontTexture;
io.Fonts->SetTexID((ImTextureID)g_FontTexture);
return true;
}
@ -209,8 +209,8 @@ void ImGui_Marmalade_InvalidateDeviceObjects()
if (g_FontTexture)
{
ImGui::GetIO().Fonts->SetTexID(0);
delete g_FontTexture;
ImGui::GetIO().Fonts->TexID = 0;
g_FontTexture = NULL;
}
}
@ -220,7 +220,8 @@ bool ImGui_Marmalade_Init(bool install_callbacks)
ImGuiIO& io = ImGui::GetIO();
io.BackendPlatformName = io.BackendRendererName = "imgui_impl_marmalade";
io.KeyMap[ImGuiKey_Tab] = s3eKeyTab; // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
io.KeyMap[ImGuiKey_Tab] = s3eKeyTab
io.KeyMap[ImGuiKey_LeftArrow] = s3eKeyLeft;
io.KeyMap[ImGuiKey_RightArrow] = s3eKeyRight;
io.KeyMap[ImGuiKey_UpArrow] = s3eKeyUp;

View File

@ -4,8 +4,6 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// Missing features:
// [ ] Renderer: Multi-viewport / platform windows.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.

View File

@ -4,8 +4,6 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// Missing features:
// [ ] Renderer: Multi-viewport / platform windows.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
@ -13,6 +11,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-02-18: Metal: Change blending equation to preserve alpha in output buffer.
// 2021-01-25: Metal: Fixed texture storage mode when building on Mac Catalyst.
// 2019-05-29: Metal: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: Metal: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2019-02-11: Metal: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
@ -115,7 +115,7 @@ bool ImGui_ImplMetal_CreateFontsTexture(id<MTLDevice> device)
[g_sharedMetalContext makeFontTextureWithDevice:device];
ImGuiIO& io = ImGui::GetIO();
io.Fonts->TexID = (__bridge void *)g_sharedMetalContext.fontTexture; // ImTextureID == void*
io.Fonts->SetTexID((__bridge void *)g_sharedMetalContext.fontTexture); // ImTextureID == void*
return (g_sharedMetalContext.fontTexture != nil);
}
@ -124,7 +124,7 @@ void ImGui_ImplMetal_DestroyFontsTexture()
{
ImGuiIO& io = ImGui::GetIO();
g_sharedMetalContext.fontTexture = nil;
io.Fonts->TexID = nullptr;
io.Fonts->SetTexID(nullptr);
}
bool ImGui_ImplMetal_CreateDeviceObjects(id<MTLDevice> device)
@ -240,7 +240,7 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
height:(NSUInteger)height
mipmapped:NO];
textureDescriptor.usage = MTLTextureUsageShaderRead;
#if TARGET_OS_OSX
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
textureDescriptor.storageMode = MTLStorageModeManaged;
#else
textureDescriptor.storageMode = MTLStorageModeShared;
@ -387,10 +387,10 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
pipelineDescriptor.colorAttachments[0].pixelFormat = self.framebufferDescriptor.colorPixelFormat;
pipelineDescriptor.colorAttachments[0].blendingEnabled = YES;
pipelineDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
pipelineDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha;
pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
pipelineDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
pipelineDescriptor.depthAttachmentPixelFormat = self.framebufferDescriptor.depthPixelFormat;
pipelineDescriptor.stencilAttachmentPixelFormat = self.framebufferDescriptor.stencilPixelFormat;

View File

@ -3,7 +3,6 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
@ -19,8 +18,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2020-01-23: OpenGL: Explicitly backup, setup and restore GL_TEXTURE_ENV 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.
// 2020-01-23: OpenGL: Backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications.
// 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
@ -57,26 +56,17 @@
// OpenGL Data
static GLuint g_FontTexture = 0;
// Forward Declarations
static void ImGui_ImplOpenGL2_InitPlatformInterface();
static void ImGui_ImplOpenGL2_ShutdownPlatformInterface();
// Functions
bool ImGui_ImplOpenGL2_Init()
{
// Setup backend capabilities flags
ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = "imgui_impl_opengl2";
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplOpenGL2_InitPlatformInterface();
return true;
}
void ImGui_ImplOpenGL2_Shutdown()
{
ImGui_ImplOpenGL2_ShutdownPlatformInterface();
ImGui_ImplOpenGL2_DestroyDeviceObjects();
}
@ -91,25 +81,32 @@ static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_wid
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // In order to composite our output buffer we need to preserve alpha
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
glEnable(GL_SCISSOR_TEST);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glEnable(GL_TEXTURE_2D);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glShadeModel(GL_SMOOTH);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
// you may need to backup/reset/restore current shader using the lines below. DO NOT MODIFY THIS FILE! Add the code in your calling function:
// GLint last_program;
// glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
// glUseProgram(0);
// ImGui_ImplOpenGL2_RenderDrawData(...);
// glUseProgram(last_program)
// you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below.
// (DO NOT MODIFY THIS FILE! Add the code in your calling function)
// GLint last_program;
// glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
// glUseProgram(0);
// ImGui_ImplOpenGL2_RenderDrawData(...);
// glUseProgram(last_program)
// There are potentially many more states you could need to clear/setup that we can't access from default headers.
// e.g. glBindBuffer(GL_ARRAY_BUFFER, 0), glDisable(GL_TEXTURE_CUBE_MAP).
// Setup viewport, orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
@ -139,6 +136,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
GLint last_shade_model; glGetIntegerv(GL_SHADE_MODEL, &last_shade_model);
GLint last_tex_env_mode; glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_tex_env_mode);
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
@ -207,6 +205,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]);
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]);
glShadeModel(last_shade_model);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_tex_env_mode);
}
@ -229,7 +228,7 @@ bool ImGui_ImplOpenGL2_CreateFontsTexture()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// Store our identifier
io.Fonts->TexID = (ImTextureID)(intptr_t)g_FontTexture;
io.Fonts->SetTexID((ImTextureID)(intptr_t)g_FontTexture);
// Restore state
glBindTexture(GL_TEXTURE_2D, last_texture);
@ -243,7 +242,7 @@ void ImGui_ImplOpenGL2_DestroyFontsTexture()
{
ImGuiIO& io = ImGui::GetIO();
glDeleteTextures(1, &g_FontTexture);
io.Fonts->TexID = 0;
io.Fonts->SetTexID(0);
g_FontTexture = 0;
}
}
@ -257,31 +256,3 @@ void ImGui_ImplOpenGL2_DestroyDeviceObjects()
{
ImGui_ImplOpenGL2_DestroyFontsTexture();
}
//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------
static void ImGui_ImplOpenGL2_RenderWindow(ImGuiViewport* viewport, void*)
{
if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear))
{
ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
}
ImGui_ImplOpenGL2_RenderDrawData(viewport->DrawData);
}
static void ImGui_ImplOpenGL2_InitPlatformInterface()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Renderer_RenderWindow = ImGui_ImplOpenGL2_RenderWindow;
}
static void ImGui_ImplOpenGL2_ShutdownPlatformInterface()
{
ImGui::DestroyPlatformWindows();
}

View File

@ -3,7 +3,6 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.

View File

@ -5,7 +5,6 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
@ -14,8 +13,9 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2020-10-23: OpenGL: Save and restore current GL_PRIMITIVE_RESTART state.
// 2021-02-18: OpenGL: Change blending equation to preserve alpha in output buffer.
// 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state.
// 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state.
// 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x)
// 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader.
// 2020-07-10: OpenGL: Added support for glad2 OpenGL loader.
@ -151,10 +151,6 @@ static GLint g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
static GLuint g_AttribLocationVtxPos = 0, g_AttribLocationVtxUV = 0, g_AttribLocationVtxColor = 0; // Vertex attributes location
static unsigned int g_VboHandle = 0, g_ElementsHandle = 0;
// Forward Declarations
static void ImGui_ImplOpenGL3_InitPlatformInterface();
static void ImGui_ImplOpenGL3_ShutdownPlatformInterface();
// Functions
bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
{
@ -182,7 +178,6 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
if (g_GlVersion >= 320)
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
#endif
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
// Store GLSL version string so we can refer to it later in case we recreate shaders.
// Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure.
@ -234,15 +229,11 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
GLint current_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplOpenGL3_InitPlatformInterface();
return true;
}
void ImGui_ImplOpenGL3_Shutdown()
{
ImGui_ImplOpenGL3_ShutdownPlatformInterface();
ImGui_ImplOpenGL3_DestroyDeviceObjects();
}
@ -257,9 +248,10 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glEnable(GL_SCISSOR_TEST);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
if (g_GlVersion >= 310)
@ -270,8 +262,8 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
#endif
// Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
bool clip_origin_lower_left = true;
#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__)
bool clip_origin_lower_left = true;
GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&current_clip_origin);
if (current_clip_origin == GL_UPPER_LEFT)
clip_origin_lower_left = false;
@ -284,7 +276,9 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
float T = draw_data->DisplayPos.y;
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__)
if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left
#endif
const float ortho_projection[4][4] =
{
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
@ -295,12 +289,12 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
glUseProgram(g_ShaderHandle);
glUniform1i(g_AttribLocationTex, 0);
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
if (g_GlVersion >= 330)
glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.
#endif
(void)vertex_array_object;
#ifndef IMGUI_IMPL_OPENGL_ES2
glBindVertexArray(vertex_array_object);
@ -354,6 +348,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
GLboolean last_enable_stencil_test = glIsEnabled(GL_STENCIL_TEST);
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
GLboolean last_enable_primitive_restart = (g_GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE;
@ -442,6 +437,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
if (last_enable_stencil_test) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST);
if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
if (g_GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); }
@ -475,7 +471,7 @@ bool ImGui_ImplOpenGL3_CreateFontsTexture()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// Store our identifier
io.Fonts->TexID = (ImTextureID)(intptr_t)g_FontTexture;
io.Fonts->SetTexID((ImTextureID)(intptr_t)g_FontTexture);
// Restore state
glBindTexture(GL_TEXTURE_2D, last_texture);
@ -489,7 +485,7 @@ void ImGui_ImplOpenGL3_DestroyFontsTexture()
{
ImGuiIO& io = ImGui::GetIO();
glDeleteTextures(1, &g_FontTexture);
io.Fonts->TexID = 0;
io.Fonts->SetTexID(0);
g_FontTexture = 0;
}
}
@ -722,31 +718,3 @@ void ImGui_ImplOpenGL3_DestroyDeviceObjects()
ImGui_ImplOpenGL3_DestroyFontsTexture();
}
//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------
static void ImGui_ImplOpenGL3_RenderWindow(ImGuiViewport* viewport, void*)
{
if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear))
{
ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
}
ImGui_ImplOpenGL3_RenderDrawData(viewport->DrawData);
}
static void ImGui_ImplOpenGL3_InitPlatformInterface()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Renderer_RenderWindow = ImGui_ImplOpenGL3_RenderWindow;
}
static void ImGui_ImplOpenGL3_ShutdownPlatformInterface()
{
ImGui::DestroyPlatformWindows();
}

View File

@ -5,7 +5,6 @@
// Implemented features:
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.

View File

@ -7,7 +7,6 @@
// [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
// Issues:
// [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters]..
// [ ] Platform: Multi-viewport / platform windows.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.

View File

@ -7,7 +7,6 @@
// [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
// Issues:
// [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters]..
// [ ] Platform: Multi-viewport / platform windows.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
@ -19,6 +18,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-01-27: Inputs: Added a fix for mouse position not being reported when mouse buttons other than left one are down.
// 2020-10-28: Inputs: Added a fix for handling keypad-enter key.
// 2020-05-25: Inputs: Added a fix for missing trackpad clicks when done with "soft tap".
// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
@ -227,7 +227,7 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
return io.WantCaptureMouse;
}
if (event.type == NSEventTypeMouseMoved || event.type == NSEventTypeLeftMouseDragged)
if (event.type == NSEventTypeMouseMoved || event.type == NSEventTypeLeftMouseDragged || event.type == NSEventTypeRightMouseDragged || event.type == NSEventTypeOtherMouseDragged)
{
NSPoint mousePoint = event.locationInWindow;
mousePoint = [view convertPoint:mousePoint fromView:nil];

View File

@ -8,10 +8,8 @@
// [X] Platform: Clipboard support.
// [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE).
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// Missing features:
// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
// [ ] Platform: Multi-viewport + Minimized windows seems to break mouse wheel events (at least under Windows).
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
@ -19,7 +17,6 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2020-05-25: Misc: Report a zero display-size when window is minimized, to be consistent with other backends.
// 2020-02-20: Inputs: Fixed mapping for ImGuiKey_KeyPadEnter (using SDL_SCANCODE_KP_ENTER instead of SDL_SCANCODE_RETURN2).
// 2019-12-17: Inputs: On Wayland, use SDL_GetMouseState (because there is no global mouse state).
@ -51,7 +48,6 @@
#include "imgui_impl_sdl.h"
// SDL
// (the multi-viewports feature requires SDL features supported from SDL 2.0.4+. SDL 2.0.5+ is highly recommended)
#include <SDL.h>
#include <SDL_syswm.h>
#if defined(__APPLE__)
@ -59,15 +55,7 @@
#endif
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE SDL_VERSION_ATLEAST(2,0,4)
#define SDL_HAS_WINDOW_ALPHA SDL_VERSION_ATLEAST(2,0,5)
#define SDL_HAS_ALWAYS_ON_TOP SDL_VERSION_ATLEAST(2,0,5)
#define SDL_HAS_USABLE_DISPLAY_BOUNDS SDL_VERSION_ATLEAST(2,0,5)
#define SDL_HAS_PER_MONITOR_DPI SDL_VERSION_ATLEAST(2,0,4)
#define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6)
#define SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH SDL_VERSION_ATLEAST(2,0,5)
#if !SDL_HAS_VULKAN
static const Uint32 SDL_WINDOW_VULKAN = 0x10000000;
#endif
// Data
static SDL_Window* g_Window = NULL;
@ -76,12 +64,6 @@ static bool g_MousePressed[3] = { false, false, false };
static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};
static char* g_ClipboardTextData = NULL;
static bool g_MouseCanUseGlobalState = true;
static bool g_UseVulkan = false;
// Forward Declarations
static void ImGui_ImplSDL2_UpdateMonitors();
static void ImGui_ImplSDL2_InitPlatformInterface(SDL_Window* window, void* sdl_gl_context);
static void ImGui_ImplSDL2_ShutdownPlatformInterface();
static const char* ImGui_ImplSDL2_GetClipboardText(void*)
{
@ -142,38 +124,21 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
#endif
return true;
}
// Multi-viewport support
case SDL_WINDOWEVENT:
Uint8 window_event = event->window.event;
if (window_event == SDL_WINDOWEVENT_CLOSE || window_event == SDL_WINDOWEVENT_MOVED || window_event == SDL_WINDOWEVENT_RESIZED)
if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle((void*)SDL_GetWindowFromID(event->window.windowID)))
{
if (window_event == SDL_WINDOWEVENT_CLOSE)
viewport->PlatformRequestClose = true;
if (window_event == SDL_WINDOWEVENT_MOVED)
viewport->PlatformRequestMove = true;
if (window_event == SDL_WINDOWEVENT_RESIZED)
viewport->PlatformRequestResize = true;
return true;
}
break;
}
return false;
}
static bool ImGui_ImplSDL2_Init(SDL_Window* window, void* sdl_gl_context)
static bool ImGui_ImplSDL2_Init(SDL_Window* window)
{
g_Window = window;
// Setup backend capabilities flags
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
#endif
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
io.BackendPlatformName = "imgui_impl_sdl";
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB;
io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT;
io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT;
@ -215,31 +180,22 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, void* sdl_gl_context)
// Check and store if we are on Wayland
g_MouseCanUseGlobalState = strncmp(SDL_GetCurrentVideoDriver(), "wayland", 7) != 0;
// Our mouse update function expect PlatformHandle to be filled for the main viewport
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
main_viewport->PlatformHandle = (void*)window;
#if defined(_WIN32)
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWindowWMInfo(window, &info))
main_viewport->PlatformHandleRaw = info.info.win.window;
#ifdef _WIN32
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWindowWMInfo(window, &wmInfo);
io.ImeWindowHandle = wmInfo.info.win.window;
#else
(void)window;
#endif
// Update monitors
ImGui_ImplSDL2_UpdateMonitors();
// We need SDL_CaptureMouse(), SDL_GetGlobalMouseState() from SDL 2.0.4+ to support multiple viewports.
// We left the call to ImGui_ImplSDL2_InitPlatformInterface() outside of #ifdef to avoid unused-function warnings.
if ((io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) && (io.BackendFlags & ImGuiBackendFlags_PlatformHasViewports))
ImGui_ImplSDL2_InitPlatformInterface(window, sdl_gl_context);
return true;
}
bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context)
{
(void)sdl_gl_context; // Viewport branch will need this.
return ImGui_ImplSDL2_Init(window, sdl_gl_context);
return ImGui_ImplSDL2_Init(window);
}
bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window)
@ -247,8 +203,7 @@ bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window)
#if !SDL_HAS_VULKAN
IM_ASSERT(0 && "Unsupported");
#endif
g_UseVulkan = true;
return ImGui_ImplSDL2_Init(window, NULL);
return ImGui_ImplSDL2_Init(window);
}
bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window)
@ -256,17 +211,16 @@ bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window)
#if !defined(_WIN32)
IM_ASSERT(0 && "Unsupported");
#endif
return ImGui_ImplSDL2_Init(window, NULL);
return ImGui_ImplSDL2_Init(window);
}
bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window)
{
return ImGui_ImplSDL2_Init(window, NULL);
return ImGui_ImplSDL2_Init(window);
}
void ImGui_ImplSDL2_Shutdown()
{
ImGui_ImplSDL2_ShutdownPlatformInterface();
g_Window = NULL;
// Destroy last known clipboard data
@ -280,68 +234,39 @@ void ImGui_ImplSDL2_Shutdown()
memset(g_MouseCursors, 0, sizeof(g_MouseCursors));
}
// This code is incredibly messy because some of the functions we need for full viewport support are not available in SDL < 2.0.4.
static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
{
ImGuiIO& io = ImGui::GetIO();
io.MouseHoveredViewport = 0;
// [1]
// Only when requested by io.WantSetMousePos: set OS mouse pos from Dear ImGui mouse pos.
// (rarely used, mostly when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
// Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
if (io.WantSetMousePos)
{
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
SDL_WarpMouseGlobal((int)io.MousePos.x, (int)io.MousePos.y);
else
#endif
SDL_WarpMouseInWindow(g_Window, (int)io.MousePos.x, (int)io.MousePos.y);
}
SDL_WarpMouseInWindow(g_Window, (int)io.MousePos.x, (int)io.MousePos.y);
else
{
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
}
// [2]
// Set Dear ImGui mouse pos from OS mouse pos + get buttons. (this is the common behavior)
int mouse_x_local, mouse_y_local;
Uint32 mouse_buttons = SDL_GetMouseState(&mouse_x_local, &mouse_y_local);
io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
int mx, my;
Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my);
io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS)
if (g_MouseCanUseGlobalState)
SDL_Window* focused_window = SDL_GetKeyboardFocus();
if (g_Window == focused_window)
{
// SDL 2.0.4 and later has SDL_GetGlobalMouseState() and SDL_CaptureMouse()
int mouse_x_global, mouse_y_global;
SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
if (g_MouseCanUseGlobalState)
{
// Multi-viewport mode: mouse position in OS absolute coordinates (io.MousePos is (0,0) when the mouse is on the upper-left of the primary monitor)
if (SDL_Window* focused_window = SDL_GetKeyboardFocus())
if (ImGui::FindViewportByPlatformHandle((void*)focused_window) != NULL)
io.MousePos = ImVec2((float)mouse_x_global, (float)mouse_y_global);
// SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?)
// The creation of a new windows at runtime and SDL_CaptureMouse both seems to severely mess up with that, so we retrieve that position globally.
// Won't use this workaround when on Wayland, as there is no global mouse position.
int wx, wy;
SDL_GetWindowPosition(focused_window, &wx, &wy);
SDL_GetGlobalMouseState(&mx, &my);
mx -= wx;
my -= wy;
}
else
{
// Single-viewport mode: mouse position in client window coordinatesio.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_INPUT_FOCUS)
{
int window_x, window_y;
SDL_GetWindowPosition(g_Window, &window_x, &window_y);
io.MousePos = ImVec2((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y));
}
}
}
else
{
if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_INPUT_FOCUS)
io.MousePos = ImVec2((float)mouse_x_local, (float)mouse_y_local);
io.MousePos = ImVec2((float)mx, (float)my);
}
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger the OS window resize cursor.
@ -349,9 +274,8 @@ static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
bool any_mouse_button_down = ImGui::IsAnyMouseDown();
SDL_CaptureMouse(any_mouse_button_down ? SDL_TRUE : SDL_FALSE);
#else
// SDL 2.0.3 and before: single-viewport only
if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_INPUT_FOCUS)
io.MousePos = ImVec2((float)mouse_x_local, (float)mouse_y_local);
io.MousePos = ImVec2((float)mx, (float)my);
#endif
}
@ -416,34 +340,6 @@ static void ImGui_ImplSDL2_UpdateGamepads()
#undef MAP_ANALOG
}
// FIXME-PLATFORM: SDL doesn't have an event to notify the application of display/monitor changes
static void ImGui_ImplSDL2_UpdateMonitors()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Monitors.resize(0);
int display_count = SDL_GetNumVideoDisplays();
for (int n = 0; n < display_count; n++)
{
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.
ImGuiPlatformMonitor monitor;
SDL_Rect r;
SDL_GetDisplayBounds(n, &r);
monitor.MainPos = monitor.WorkPos = ImVec2((float)r.x, (float)r.y);
monitor.MainSize = monitor.WorkSize = ImVec2((float)r.w, (float)r.h);
#if SDL_HAS_USABLE_DISPLAY_BOUNDS
SDL_GetDisplayUsableBounds(n, &r);
monitor.WorkPos = ImVec2((float)r.x, (float)r.y);
monitor.WorkSize = ImVec2((float)r.w, (float)r.h);
#endif
#if SDL_HAS_PER_MONITOR_DPI
float dpi = 0.0f;
if (!SDL_GetDisplayDPI(n, &dpi, NULL, NULL))
monitor.DpiScale = dpi / 96.0f;
#endif
platform_io.Monitors.push_back(monitor);
}
}
void ImGui_ImplSDL2_NewFrame(SDL_Window* window)
{
ImGuiIO& io = ImGui::GetIO();
@ -472,248 +368,3 @@ void ImGui_ImplSDL2_NewFrame(SDL_Window* window)
// Update game controllers (if enabled and available)
ImGui_ImplSDL2_UpdateGamepads();
}
//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------
// Helper structure we store in the void* RenderUserData field of each ImGuiViewport to easily retrieve our backend data.
struct ImGuiViewportDataSDL2
{
SDL_Window* Window;
Uint32 WindowID;
bool WindowOwned;
SDL_GLContext GLContext;
ImGuiViewportDataSDL2() { Window = NULL; WindowID = 0; WindowOwned = false; GLContext = NULL; }
~ImGuiViewportDataSDL2() { IM_ASSERT(Window == NULL && GLContext == NULL); }
};
static void ImGui_ImplSDL2_CreateWindow(ImGuiViewport* viewport)
{
ImGuiViewportDataSDL2* data = IM_NEW(ImGuiViewportDataSDL2)();
viewport->PlatformUserData = data;
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
ImGuiViewportDataSDL2* main_viewport_data = (ImGuiViewportDataSDL2*)main_viewport->PlatformUserData;
// Share GL resources with main context
bool use_opengl = (main_viewport_data->GLContext != NULL);
SDL_GLContext backup_context = NULL;
if (use_opengl)
{
backup_context = SDL_GL_GetCurrentContext();
SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
SDL_GL_MakeCurrent(main_viewport_data->Window, main_viewport_data->GLContext);
}
Uint32 sdl_flags = 0;
sdl_flags |= use_opengl ? SDL_WINDOW_OPENGL : (g_UseVulkan ? SDL_WINDOW_VULKAN : 0);
sdl_flags |= SDL_GetWindowFlags(g_Window) & SDL_WINDOW_ALLOW_HIGHDPI;
sdl_flags |= SDL_WINDOW_HIDDEN;
sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? SDL_WINDOW_BORDERLESS : 0;
sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? 0 : SDL_WINDOW_RESIZABLE;
#if !defined(_WIN32)
// See SDL hack in ImGui_ImplSDL2_ShowWindow().
sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoTaskBarIcon) ? SDL_WINDOW_SKIP_TASKBAR : 0;
#endif
#if SDL_HAS_ALWAYS_ON_TOP
sdl_flags |= (viewport->Flags & ImGuiViewportFlags_TopMost) ? SDL_WINDOW_ALWAYS_ON_TOP : 0;
#endif
data->Window = SDL_CreateWindow("No Title Yet", (int)viewport->Pos.x, (int)viewport->Pos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags);
data->WindowOwned = true;
if (use_opengl)
{
data->GLContext = SDL_GL_CreateContext(data->Window);
SDL_GL_SetSwapInterval(0);
}
if (use_opengl && backup_context)
SDL_GL_MakeCurrent(data->Window, backup_context);
viewport->PlatformHandle = (void*)data->Window;
#if defined(_WIN32)
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWindowWMInfo(data->Window, &info))
viewport->PlatformHandleRaw = info.info.win.window;
#endif
}
static void ImGui_ImplSDL2_DestroyWindow(ImGuiViewport* viewport)
{
if (ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData)
{
if (data->GLContext && data->WindowOwned)
SDL_GL_DeleteContext(data->GLContext);
if (data->Window && data->WindowOwned)
SDL_DestroyWindow(data->Window);
data->GLContext = NULL;
data->Window = NULL;
IM_DELETE(data);
}
viewport->PlatformUserData = viewport->PlatformHandle = NULL;
}
static void ImGui_ImplSDL2_ShowWindow(ImGuiViewport* viewport)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
#if defined(_WIN32)
HWND hwnd = (HWND)viewport->PlatformHandleRaw;
// SDL hack: Hide icon from task bar
// Note: SDL 2.0.6+ has a SDL_WINDOW_SKIP_TASKBAR flag which is supported under Windows but the way it create the window breaks our seamless transition.
if (viewport->Flags & ImGuiViewportFlags_NoTaskBarIcon)
{
LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
ex_style &= ~WS_EX_APPWINDOW;
ex_style |= WS_EX_TOOLWINDOW;
::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style);
}
// SDL hack: SDL always activate/focus windows :/
if (viewport->Flags & ImGuiViewportFlags_NoFocusOnAppearing)
{
::ShowWindow(hwnd, SW_SHOWNA);
return;
}
#endif
SDL_ShowWindow(data->Window);
}
static ImVec2 ImGui_ImplSDL2_GetWindowPos(ImGuiViewport* viewport)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
int x = 0, y = 0;
SDL_GetWindowPosition(data->Window, &x, &y);
return ImVec2((float)x, (float)y);
}
static void ImGui_ImplSDL2_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
SDL_SetWindowPosition(data->Window, (int)pos.x, (int)pos.y);
}
static ImVec2 ImGui_ImplSDL2_GetWindowSize(ImGuiViewport* viewport)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
int w = 0, h = 0;
SDL_GetWindowSize(data->Window, &w, &h);
return ImVec2((float)w, (float)h);
}
static void ImGui_ImplSDL2_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
SDL_SetWindowSize(data->Window, (int)size.x, (int)size.y);
}
static void ImGui_ImplSDL2_SetWindowTitle(ImGuiViewport* viewport, const char* title)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
SDL_SetWindowTitle(data->Window, title);
}
#if SDL_HAS_WINDOW_ALPHA
static void ImGui_ImplSDL2_SetWindowAlpha(ImGuiViewport* viewport, float alpha)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
SDL_SetWindowOpacity(data->Window, alpha);
}
#endif
static void ImGui_ImplSDL2_SetWindowFocus(ImGuiViewport* viewport)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
SDL_RaiseWindow(data->Window);
}
static bool ImGui_ImplSDL2_GetWindowFocus(ImGuiViewport* viewport)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
return (SDL_GetWindowFlags(data->Window) & SDL_WINDOW_INPUT_FOCUS) != 0;
}
static bool ImGui_ImplSDL2_GetWindowMinimized(ImGuiViewport* viewport)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
return (SDL_GetWindowFlags(data->Window) & SDL_WINDOW_MINIMIZED) != 0;
}
static void ImGui_ImplSDL2_RenderWindow(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
if (data->GLContext)
SDL_GL_MakeCurrent(data->Window, data->GLContext);
}
static void ImGui_ImplSDL2_SwapBuffers(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
if (data->GLContext)
{
SDL_GL_MakeCurrent(data->Window, data->GLContext);
SDL_GL_SwapWindow(data->Window);
}
}
// Vulkan support (the Vulkan renderer needs to call a platform-side support function to create the surface)
// SDL is graceful enough to _not_ need <vulkan/vulkan.h> so we can safely include this.
#if SDL_HAS_VULKAN
#include <SDL_vulkan.h>
static int ImGui_ImplSDL2_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_instance, const void* vk_allocator, ImU64* out_vk_surface)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
(void)vk_allocator;
SDL_bool ret = SDL_Vulkan_CreateSurface(data->Window, (VkInstance)vk_instance, (VkSurfaceKHR*)out_vk_surface);
return ret ? 0 : 1; // ret ? VK_SUCCESS : VK_NOT_READY
}
#endif // SDL_HAS_VULKAN
static void ImGui_ImplSDL2_InitPlatformInterface(SDL_Window* window, void* sdl_gl_context)
{
// Register platform interface (will be coupled with a renderer interface)
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Platform_CreateWindow = ImGui_ImplSDL2_CreateWindow;
platform_io.Platform_DestroyWindow = ImGui_ImplSDL2_DestroyWindow;
platform_io.Platform_ShowWindow = ImGui_ImplSDL2_ShowWindow;
platform_io.Platform_SetWindowPos = ImGui_ImplSDL2_SetWindowPos;
platform_io.Platform_GetWindowPos = ImGui_ImplSDL2_GetWindowPos;
platform_io.Platform_SetWindowSize = ImGui_ImplSDL2_SetWindowSize;
platform_io.Platform_GetWindowSize = ImGui_ImplSDL2_GetWindowSize;
platform_io.Platform_SetWindowFocus = ImGui_ImplSDL2_SetWindowFocus;
platform_io.Platform_GetWindowFocus = ImGui_ImplSDL2_GetWindowFocus;
platform_io.Platform_GetWindowMinimized = ImGui_ImplSDL2_GetWindowMinimized;
platform_io.Platform_SetWindowTitle = ImGui_ImplSDL2_SetWindowTitle;
platform_io.Platform_RenderWindow = ImGui_ImplSDL2_RenderWindow;
platform_io.Platform_SwapBuffers = ImGui_ImplSDL2_SwapBuffers;
#if SDL_HAS_WINDOW_ALPHA
platform_io.Platform_SetWindowAlpha = ImGui_ImplSDL2_SetWindowAlpha;
#endif
#if SDL_HAS_VULKAN
platform_io.Platform_CreateVkSurface = ImGui_ImplSDL2_CreateVkSurface;
#endif
// SDL2 by default doesn't pass mouse clicks to the application when the click focused a window. This is getting in the way of our interactions and we disable that behavior.
#if SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
#endif
// Register main window handle (which is owned by the main application, not by us)
// This is mostly for simplicity and consistency, so that our code (e.g. mouse handling etc.) can use same logic for main and secondary viewports.
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
ImGuiViewportDataSDL2* data = IM_NEW(ImGuiViewportDataSDL2)();
data->Window = window;
data->WindowID = SDL_GetWindowID(window);
data->WindowOwned = false;
data->GLContext = sdl_gl_context;
main_viewport->PlatformUserData = data;
main_viewport->PlatformHandle = data->Window;
}
static void ImGui_ImplSDL2_ShutdownPlatformInterface()
{
}

View File

@ -7,10 +7,8 @@
// [X] Platform: Clipboard support.
// [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE).
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// Missing features:
// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
// [ ] Platform: Multi-viewport + Minimized windows seems to break mouse wheel events (at least under Windows).
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.

View File

@ -3,7 +3,6 @@
// Implemented features:
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// [x] Platform: Multi-viewport / platform windows. With issues (flickering when creating a new viewport).
// Missing features:
// [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this backend! See https://github.com/ocornut/imgui/pull/914
@ -23,6 +22,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-02-18: Vulkan: Change blending equation to preserve alpha in output buffer.
// 2021-01-27: Vulkan: Added support for custom function load and IMGUI_IMPL_VULKAN_NO_PROTOTYPES by using ImGui_ImplVulkan_LoadFunctions().
// 2020-11-11: Vulkan: Added support for specifying which subpass to reference during VkPipeline creation.
// 2020-09-07: Vulkan: Added VkPipeline parameter to ImGui_ImplVulkan_RenderDrawData (default to one passed to ImGui_ImplVulkan_Init).
// 2020-05-04: Vulkan: Fixed crash if initial frame has no vertices.
@ -49,7 +50,6 @@
// 2016-10-18: Vulkan: Add location decorators & change to use structs as in/out in glsl, update embedded spv (produced with glslangValidator -x). Null the released resources.
// 2016-08-27: Vulkan: Fix Vulkan example for use when a depth buffer is active.
#include "imgui.h"
#include "imgui_impl_vulkan.h"
#include <stdio.h>
@ -74,18 +74,6 @@ struct ImGui_ImplVulkanH_WindowRenderBuffers
ImGui_ImplVulkanH_FrameRenderBuffers* FrameRenderBuffers;
};
// For multi-viewport support:
// Helper structure we store in the void* RenderUserData field of each ImGuiViewport to easily retrieve our backend data.
struct ImGuiViewportDataVulkan
{
bool WindowOwned;
ImGui_ImplVulkanH_Window Window; // Used by secondary viewports only
ImGui_ImplVulkanH_WindowRenderBuffers RenderBuffers; // Used by all viewports
ImGuiViewportDataVulkan() { WindowOwned = false; memset(&RenderBuffers, 0, sizeof(RenderBuffers)); }
~ImGuiViewportDataVulkan() { }
};
// Vulkan data
static ImGui_ImplVulkan_InitInfo g_VulkanInitInfo = {};
static VkRenderPass g_RenderPass = VK_NULL_HANDLE;
@ -98,6 +86,11 @@ static VkPipeline g_Pipeline = VK_NULL_HANDLE;
static uint32_t g_Subpass = 0;
static VkShaderModule g_ShaderModuleVert;
static VkShaderModule g_ShaderModuleFrag;
#ifdef VK_NO_PROTOTYPES
static bool g_FunctionsLoaded = false;
#else
static bool g_FunctionsLoaded = true;
#endif
// Font data
static VkSampler g_FontSampler = VK_NULL_HANDLE;
@ -107,6 +100,9 @@ static VkImageView g_FontView = VK_NULL_HANDLE;
static VkDeviceMemory g_UploadBufferMemory = VK_NULL_HANDLE;
static VkBuffer g_UploadBuffer = VK_NULL_HANDLE;
// Render buffers
static ImGui_ImplVulkanH_WindowRenderBuffers g_MainWindowRenderBuffers;
// Forward Declarations
bool ImGui_ImplVulkan_CreateDeviceObjects();
void ImGui_ImplVulkan_DestroyDeviceObjects();
@ -114,18 +110,82 @@ void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd
void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator);
void ImGui_ImplVulkanH_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkanH_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkanH_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
void ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(VkDevice device, const VkAllocationCallbacks* allocator);
void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator);
// Vulkan prototypes for use with custom loaders
// (see description of IMGUI_IMPL_VULKAN_NO_PROTOTYPES in imgui_impl_vulkan.h
#ifdef VK_NO_PROTOTYPES
#define IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_MAP_MACRO) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateCommandBuffers) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateDescriptorSets) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateMemory) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkBindBufferMemory) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkBindImageMemory) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBindDescriptorSets) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBindIndexBuffer) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBindPipeline) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBindVertexBuffers) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdCopyBufferToImage) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdDrawIndexed) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdPipelineBarrier) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdPushConstants) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdSetScissor) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdSetViewport) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateBuffer) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateCommandPool) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateDescriptorSetLayout) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateFence) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateFramebuffer) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateGraphicsPipelines) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateImage) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateImageView) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreatePipelineLayout) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateRenderPass) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateSampler) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateSemaphore) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateShaderModule) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateSwapchainKHR) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyBuffer) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyCommandPool) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyDescriptorSetLayout) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyFence) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyFramebuffer) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyImage) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyImageView) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyPipeline) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyPipelineLayout) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyRenderPass) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySampler) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySemaphore) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyShaderModule) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySurfaceKHR) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySwapchainKHR) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDeviceWaitIdle) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkFlushMappedMemoryRanges) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeCommandBuffers) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeMemory) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetBufferMemoryRequirements) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetImageMemoryRequirements) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceMemoryProperties) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfaceFormatsKHR) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfacePresentModesKHR) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetSwapchainImagesKHR) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkMapMemory) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkUnmapMemory) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkUpdateDescriptorSets)
// Define function pointers
#define IMGUI_VULKAN_FUNC_DEF(func) static PFN_##func func;
IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_DEF)
#undef IMGUI_VULKAN_FUNC_DEF
#endif // VK_NO_PROTOTYPES
//-----------------------------------------------------------------------------
// SHADERS
//-----------------------------------------------------------------------------
// Forward Declarations
static void ImGui_ImplVulkan_InitPlatformInterface();
static void ImGui_ImplVulkan_ShutdownPlatformInterface();
// glsl_shader.vert, compiled with:
// # glslangValidator -V -x -o glsl_shader.vert.u32 glsl_shader.vert
/*
@ -343,10 +403,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
if (pipeline == VK_NULL_HANDLE)
pipeline = g_Pipeline;
// Allocate array to store enough vertex/index buffers. Each unique viewport gets its own storage.
ImGuiViewportDataVulkan* viewport_renderer_data = (ImGuiViewportDataVulkan*)draw_data->OwnerViewport->RendererUserData;
IM_ASSERT(viewport_renderer_data != NULL);
ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &viewport_renderer_data->RenderBuffers;
// Allocate array to store enough vertex/index buffers
ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &g_MainWindowRenderBuffers;
if (wrb->FrameRenderBuffers == NULL)
{
wrb->Index = 0;
@ -604,7 +662,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
}
// Store our identifier
io.Fonts->TexID = (ImTextureID)(intptr_t)g_FontImage;
io.Fonts->SetTexID((ImTextureID)(intptr_t)g_FontImage);
return true;
}
@ -758,8 +816,8 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC
color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD;
color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD;
color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
@ -889,7 +947,7 @@ void ImGui_ImplVulkan_DestroyFontUploadObjects()
void ImGui_ImplVulkan_DestroyDeviceObjects()
{
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(v->Device, v->Allocator);
ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &g_MainWindowRenderBuffers, v->Allocator);
ImGui_ImplVulkan_DestroyFontUploadObjects();
if (g_ShaderModuleVert) { vkDestroyShaderModule(v->Device, g_ShaderModuleVert, v->Allocator); g_ShaderModuleVert = VK_NULL_HANDLE; }
@ -903,13 +961,35 @@ void ImGui_ImplVulkan_DestroyDeviceObjects()
if (g_Pipeline) { vkDestroyPipeline(v->Device, g_Pipeline, v->Allocator); g_Pipeline = VK_NULL_HANDLE; }
}
bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data)
{
// Load function pointers
// You can use the default Vulkan loader using:
// ImGui_ImplVulkan_LoadFunctions([](const char* function_name, void*) { return vkGetInstanceProcAddr(your_vk_isntance, function_name); });
// But this would be equivalent to not setting VK_NO_PROTOTYPES.
#ifdef VK_NO_PROTOTYPES
#define IMGUI_VULKAN_FUNC_LOAD(func) \
func = reinterpret_cast<decltype(func)>(loader_func(#func, user_data)); \
if (func == NULL) \
return false;
IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_LOAD)
#undef IMGUI_VULKAN_FUNC_LOAD
#else
IM_UNUSED(loader_func);
IM_UNUSED(user_data);
#endif
g_FunctionsLoaded = true;
return true;
}
bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass)
{
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
// Setup backend capabilities flags
ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = "imgui_impl_vulkan";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
IM_ASSERT(info->Instance != VK_NULL_HANDLE);
IM_ASSERT(info->PhysicalDevice != VK_NULL_HANDLE);
@ -926,29 +1006,12 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend
ImGui_ImplVulkan_CreateDeviceObjects();
// Our render function expect RendererUserData to be storing the window render buffer we need (for the main viewport we won't use ->Window)
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
main_viewport->RendererUserData = IM_NEW(ImGuiViewportDataVulkan)();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplVulkan_InitPlatformInterface();
return true;
}
void ImGui_ImplVulkan_Shutdown()
{
// First destroy objects in all viewports
ImGui_ImplVulkan_DestroyDeviceObjects();
// Manually delete main viewport render data in-case we haven't initialized for viewports
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
if (ImGuiViewportDataVulkan* data = (ImGuiViewportDataVulkan*)main_viewport->RendererUserData)
IM_DELETE(data);
main_viewport->RendererUserData = NULL;
// Clean up windows
ImGui_ImplVulkan_ShutdownPlatformInterface();
}
void ImGui_ImplVulkan_NewFrame()
@ -961,12 +1024,10 @@ void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count)
if (g_VulkanInitInfo.MinImageCount == min_image_count)
return;
IM_ASSERT(0); // FIXME-VIEWPORT: Unsupported. Need to recreate all swap chains!
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
VkResult err = vkDeviceWaitIdle(v->Device);
check_vk_result(err);
ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(v->Device, v->Allocator);
ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &g_MainWindowRenderBuffers, v->Allocator);
g_VulkanInitInfo.MinImageCount = min_image_count;
}
@ -989,6 +1050,7 @@ void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count)
VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space)
{
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
IM_ASSERT(request_formats != NULL);
IM_ASSERT(request_formats_count > 0);
@ -1033,6 +1095,7 @@ VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physic
VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count)
{
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
IM_ASSERT(request_modes != NULL);
IM_ASSERT(request_modes_count > 0);
@ -1283,9 +1346,9 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
// Create or resize window
void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int width, int height, uint32_t min_image_count)
{
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
(void)instance;
ImGui_ImplVulkanH_CreateWindowSwapChain(physical_device, device, wd, allocator, width, height, min_image_count);
//ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline, g_VulkanInitInfo.Subpass);
ImGui_ImplVulkanH_CreateWindowCommandBuffers(physical_device, device, wd, queue_family, allocator);
}
@ -1350,193 +1413,3 @@ void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVul
buffers->Index = 0;
buffers->Count = 0;
}
void ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(VkDevice device, const VkAllocationCallbacks* allocator)
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
for (int n = 0; n < platform_io.Viewports.Size; n++)
if (ImGuiViewportDataVulkan* data = (ImGuiViewportDataVulkan*)platform_io.Viewports[n]->RendererUserData)
ImGui_ImplVulkanH_DestroyWindowRenderBuffers(device, &data->RenderBuffers, allocator);
}
//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------
static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport)
{
ImGuiViewportDataVulkan* data = IM_NEW(ImGuiViewportDataVulkan)();
viewport->RendererUserData = data;
ImGui_ImplVulkanH_Window* wd = &data->Window;
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
// Create surface
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
VkResult err = (VkResult)platform_io.Platform_CreateVkSurface(viewport, (ImU64)v->Instance, (const void*)v->Allocator, (ImU64*)&wd->Surface);
check_vk_result(err);
// Check for WSI support
VkBool32 res;
vkGetPhysicalDeviceSurfaceSupportKHR(v->PhysicalDevice, v->QueueFamily, wd->Surface, &res);
if (res != VK_TRUE)
{
IM_ASSERT(0); // Error: no WSI support on physical device
return;
}
// Select Surface Format
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(v->PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
// Select Present Mode
// FIXME-VULKAN: Even thought mailbox seems to get us maximum framerate with a single window, it halves framerate with a second window etc. (w/ Nvidia and SDK 1.82.1)
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR };
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(v->PhysicalDevice, wd->Surface, &present_modes[0], IM_ARRAYSIZE(present_modes));
//printf("[vulkan] Secondary window selected PresentMode = %d\n", wd->PresentMode);
// Create SwapChain, RenderPass, Framebuffer, etc.
wd->ClearEnable = (viewport->Flags & ImGuiViewportFlags_NoRendererClear) ? false : true;
ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, wd, v->QueueFamily, v->Allocator, (int)viewport->Size.x, (int)viewport->Size.y, v->MinImageCount);
data->WindowOwned = true;
}
static void ImGui_ImplVulkan_DestroyWindow(ImGuiViewport* viewport)
{
// The main viewport (owned by the application) will always have RendererUserData == NULL since we didn't create the data for it.
if (ImGuiViewportDataVulkan* data = (ImGuiViewportDataVulkan*)viewport->RendererUserData)
{
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
if (data->WindowOwned)
ImGui_ImplVulkanH_DestroyWindow(v->Instance, v->Device, &data->Window, v->Allocator);
ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &data->RenderBuffers, v->Allocator);
IM_DELETE(data);
}
viewport->RendererUserData = NULL;
}
static void ImGui_ImplVulkan_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
{
ImGuiViewportDataVulkan* data = (ImGuiViewportDataVulkan*)viewport->RendererUserData;
if (data == NULL) // This is NULL for the main viewport (which is left to the user/app to handle)
return;
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
data->Window.ClearEnable = (viewport->Flags & ImGuiViewportFlags_NoRendererClear) ? false : true;
ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, &data->Window, v->QueueFamily, v->Allocator, (int)size.x, (int)size.y, v->MinImageCount);
}
static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataVulkan* data = (ImGuiViewportDataVulkan*)viewport->RendererUserData;
ImGui_ImplVulkanH_Window* wd = &data->Window;
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
VkResult err;
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex];
ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[wd->SemaphoreIndex];
{
for (;;)
{
err = vkWaitForFences(v->Device, 1, &fd->Fence, VK_TRUE, 100);
if (err == VK_SUCCESS) break;
if (err == VK_TIMEOUT) continue;
check_vk_result(err);
}
{
err = vkAcquireNextImageKHR(v->Device, wd->Swapchain, UINT64_MAX, fsd->ImageAcquiredSemaphore, VK_NULL_HANDLE, &wd->FrameIndex);
check_vk_result(err);
fd = &wd->Frames[wd->FrameIndex];
}
{
err = vkResetCommandPool(v->Device, fd->CommandPool, 0);
check_vk_result(err);
VkCommandBufferBeginInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
err = vkBeginCommandBuffer(fd->CommandBuffer, &info);
check_vk_result(err);
}
{
ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
VkRenderPassBeginInfo info = {};
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
info.renderPass = wd->RenderPass;
info.framebuffer = fd->Framebuffer;
info.renderArea.extent.width = wd->Width;
info.renderArea.extent.height = wd->Height;
info.clearValueCount = (viewport->Flags & ImGuiViewportFlags_NoRendererClear) ? 0 : 1;
info.pClearValues = (viewport->Flags & ImGuiViewportFlags_NoRendererClear) ? NULL : &wd->ClearValue;
vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE);
}
}
ImGui_ImplVulkan_RenderDrawData(viewport->DrawData, fd->CommandBuffer, wd->Pipeline);
{
vkCmdEndRenderPass(fd->CommandBuffer);
{
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkSubmitInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
info.waitSemaphoreCount = 1;
info.pWaitSemaphores = &fsd->ImageAcquiredSemaphore;
info.pWaitDstStageMask = &wait_stage;
info.commandBufferCount = 1;
info.pCommandBuffers = &fd->CommandBuffer;
info.signalSemaphoreCount = 1;
info.pSignalSemaphores = &fsd->RenderCompleteSemaphore;
err = vkEndCommandBuffer(fd->CommandBuffer);
check_vk_result(err);
err = vkResetFences(v->Device, 1, &fd->Fence);
check_vk_result(err);
err = vkQueueSubmit(v->Queue, 1, &info, fd->Fence);
check_vk_result(err);
}
}
}
static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport, void*)
{
ImGuiViewportDataVulkan* data = (ImGuiViewportDataVulkan*)viewport->RendererUserData;
ImGui_ImplVulkanH_Window* wd = &data->Window;
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
VkResult err;
uint32_t present_index = wd->FrameIndex;
ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[wd->SemaphoreIndex];
VkPresentInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
info.waitSemaphoreCount = 1;
info.pWaitSemaphores = &fsd->RenderCompleteSemaphore;
info.swapchainCount = 1;
info.pSwapchains = &wd->Swapchain;
info.pImageIndices = &present_index;
err = vkQueuePresentKHR(v->Queue, &info);
check_vk_result(err);
wd->FrameIndex = (wd->FrameIndex + 1) % wd->ImageCount; // This is for the next vkWaitForFences()
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores
}
void ImGui_ImplVulkan_InitPlatformInterface()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
IM_ASSERT(platform_io.Platform_CreateVkSurface != NULL && "Platform needs to setup the CreateVkSurface handler.");
platform_io.Renderer_CreateWindow = ImGui_ImplVulkan_CreateWindow;
platform_io.Renderer_DestroyWindow = ImGui_ImplVulkan_DestroyWindow;
platform_io.Renderer_SetWindowSize = ImGui_ImplVulkan_SetWindowSize;
platform_io.Renderer_RenderWindow = ImGui_ImplVulkan_RenderWindow;
platform_io.Renderer_SwapBuffers = ImGui_ImplVulkan_SwapBuffers;
}
void ImGui_ImplVulkan_ShutdownPlatformInterface()
{
ImGui::DestroyPlatformWindows();
}

View File

@ -4,7 +4,6 @@
// Implemented features:
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// Missing features:
// [ ] Platform: Multi-viewport / platform windows.
// [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this backend! See https://github.com/ocornut/imgui/pull/914
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
@ -23,25 +22,42 @@
#pragma once
#include "imgui.h" // IMGUI_IMPL_API
// [Configuration] in order to use a custom Vulkan function loader:
// (1) You'll need to disable default Vulkan function prototypes.
// We provide a '#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES' convenience configuration flag.
// In order to make sure this is visible from the imgui_impl_vulkan.cpp compilation unit:
// - Add '#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES' in your imconfig.h file
// - Or as a compilation flag in your build system
// - Or uncomment here (not recommended because you'd be modifying imgui sources!)
// - Do not simply add it in a .cpp file!
// (2) Call ImGui_ImplVulkan_LoadFunctions() before ImGui_ImplVulkan_Init() with your custom function.
// If you have no idea what this is, leave it alone!
//#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES
// Vulkan includes
#if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES) && !defined(VK_NO_PROTOTYPES)
#define VK_NO_PROTOTYPES
#endif
#include <vulkan/vulkan.h>
// Initialization data, for ImGui_ImplVulkan_Init()
// [Please zero-clear before use!]
struct ImGui_ImplVulkan_InitInfo
{
VkInstance Instance;
VkPhysicalDevice PhysicalDevice;
VkDevice Device;
uint32_t QueueFamily;
VkQueue Queue;
VkPipelineCache PipelineCache;
VkDescriptorPool DescriptorPool;
uint32_t Subpass;
uint32_t MinImageCount; // >= 2
uint32_t ImageCount; // >= MinImageCount
VkSampleCountFlagBits MSAASamples; // >= VK_SAMPLE_COUNT_1_BIT
const VkAllocationCallbacks* Allocator;
void (*CheckVkResultFn)(VkResult err);
VkInstance Instance;
VkPhysicalDevice PhysicalDevice;
VkDevice Device;
uint32_t QueueFamily;
VkQueue Queue;
VkPipelineCache PipelineCache;
VkDescriptorPool DescriptorPool;
uint32_t Subpass;
uint32_t MinImageCount; // >= 2
uint32_t ImageCount; // >= MinImageCount
VkSampleCountFlagBits MSAASamples; // >= VK_SAMPLE_COUNT_1_BIT
const VkAllocationCallbacks* Allocator;
void (*CheckVkResultFn)(VkResult err);
};
// Called by user code
@ -53,6 +69,9 @@ IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer comm
IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontUploadObjects();
IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
// Optional: load Vulkan functions with a custom function loader
// This is only useful with IMGUI_IMPL_VULKAN_NO_PROTOTYPES / VK_NO_PROTOTYPES
IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = NULL);
//-------------------------------------------------------------------------
// Internal / Miscellaneous Vulkan Helpers
@ -61,8 +80,8 @@ IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_cou
// You probably do NOT need to use or care about those functions.
// Those functions only exist because:
// 1) they facilitate the readability and maintenance of the multiple main.cpp examples files.
// 2) the multi-viewport / platform window implementation needs them internally.
// Generally we avoid exposing any kind of superfluous high-level helpers in the bindings,
// 2) the upcoming multi-viewport feature will need them internally.
// Generally we avoid exposing any kind of superfluous high-level helpers in the backends,
// but it is too much code to duplicate everywhere so we exceptionally expose them.
//
// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).

View File

@ -0,0 +1,783 @@
// dear imgui: Renderer for WebGPU
// This needs to be used along with a Platform Binding (e.g. GLFW)
// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.)
// Implemented features:
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-02-18: Change blending equation to preserve alpha in output buffer.
// 2021-01-28: Initial version.
#include "imgui.h"
#include "imgui_impl_wgpu.h"
#include <limits.h>
#include <webgpu/webgpu.h>
#define HAS_EMSCRIPTEN_VERSION(major, minor, tiny) (__EMSCRIPTEN_major__ > (major) || (__EMSCRIPTEN_major__ == (major) && __EMSCRIPTEN_minor__ > (minor)) || (__EMSCRIPTEN_major__ == (major) && __EMSCRIPTEN_minor__ == (minor) && __EMSCRIPTEN_tiny__ >= (tiny)))
// Dear ImGui prototypes from imgui_internal.h
extern ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed = 0);
// WebGPU data
static WGPUDevice g_wgpuDevice = NULL;
static WGPUTextureFormat g_renderTargetFormat = WGPUTextureFormat_Undefined;
static WGPURenderPipeline g_pipelineState = NULL;
struct RenderResources
{
WGPUTexture FontTexture; // Font texture
WGPUTextureView FontTextureView; // Texture view for font texture
WGPUSampler Sampler; // Sampler for the font texture
WGPUBuffer Uniforms; // Shader uniforms
WGPUBindGroup CommonBindGroup; // Resources bind-group to bind the common resources to pipeline
WGPUBindGroupLayout ImageBindGroupLayout; // Bind group layout for image textures
ImGuiStorage ImageBindGroups; // Resources bind-group to bind the font/image resources to pipeline (this is a key->value map)
WGPUBindGroup ImageBindGroup; // Default font-resource of Dear ImGui
};
static RenderResources g_resources;
struct FrameResources
{
WGPUBuffer IndexBuffer;
WGPUBuffer VertexBuffer;
ImDrawIdx* IndexBufferHost;
ImDrawVert* VertexBufferHost;
int IndexBufferSize;
int VertexBufferSize;
};
static FrameResources* g_pFrameResources = NULL;
static unsigned int g_numFramesInFlight = 0;
static unsigned int g_frameIndex = UINT_MAX;
struct Uniforms
{
float MVP[4][4];
};
//-----------------------------------------------------------------------------
// SHADERS
//-----------------------------------------------------------------------------
// glsl_shader.vert, compiled with:
// # glslangValidator -V -x -o glsl_shader.vert.u32 glsl_shader.vert
/*
#version 450 core
layout(location = 0) in vec2 aPos;
layout(location = 1) in vec2 aUV;
layout(location = 2) in vec4 aColor;
layout(set=0, binding = 0) uniform transform { mat4 mvp; };
out gl_PerVertex { vec4 gl_Position; };
layout(location = 0) out struct { vec4 Color; vec2 UV; } Out;
void main()
{
Out.Color = aColor;
Out.UV = aUV;
gl_Position = mvp * vec4(aPos, 0, 1);
}
*/
static uint32_t __glsl_shader_vert_spv[] =
{
0x07230203,0x00010000,0x00080007,0x0000002c,0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
0x000a000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000b,0x0000000f,0x00000015,
0x0000001b,0x00000023,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,
0x00000000,0x00030005,0x00000009,0x00000000,0x00050006,0x00000009,0x00000000,0x6f6c6f43,
0x00000072,0x00040006,0x00000009,0x00000001,0x00005655,0x00030005,0x0000000b,0x0074754f,
0x00040005,0x0000000f,0x6c6f4361,0x0000726f,0x00030005,0x00000015,0x00565561,0x00060005,
0x00000019,0x505f6c67,0x65567265,0x78657472,0x00000000,0x00060006,0x00000019,0x00000000,
0x505f6c67,0x7469736f,0x006e6f69,0x00030005,0x0000001b,0x00000000,0x00050005,0x0000001d,
0x6e617274,0x726f6673,0x0000006d,0x00040006,0x0000001d,0x00000000,0x0070766d,0x00030005,
0x0000001f,0x00000000,0x00040005,0x00000023,0x736f5061,0x00000000,0x00040047,0x0000000b,
0x0000001e,0x00000000,0x00040047,0x0000000f,0x0000001e,0x00000002,0x00040047,0x00000015,
0x0000001e,0x00000001,0x00050048,0x00000019,0x00000000,0x0000000b,0x00000000,0x00030047,
0x00000019,0x00000002,0x00040048,0x0000001d,0x00000000,0x00000005,0x00050048,0x0000001d,
0x00000000,0x00000023,0x00000000,0x00050048,0x0000001d,0x00000000,0x00000007,0x00000010,
0x00030047,0x0000001d,0x00000002,0x00040047,0x0000001f,0x00000022,0x00000000,0x00040047,
0x0000001f,0x00000021,0x00000000,0x00040047,0x00000023,0x0000001e,0x00000000,0x00020013,
0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,0x00000020,0x00040017,
0x00000007,0x00000006,0x00000004,0x00040017,0x00000008,0x00000006,0x00000002,0x0004001e,
0x00000009,0x00000007,0x00000008,0x00040020,0x0000000a,0x00000003,0x00000009,0x0004003b,
0x0000000a,0x0000000b,0x00000003,0x00040015,0x0000000c,0x00000020,0x00000001,0x0004002b,
0x0000000c,0x0000000d,0x00000000,0x00040020,0x0000000e,0x00000001,0x00000007,0x0004003b,
0x0000000e,0x0000000f,0x00000001,0x00040020,0x00000011,0x00000003,0x00000007,0x0004002b,
0x0000000c,0x00000013,0x00000001,0x00040020,0x00000014,0x00000001,0x00000008,0x0004003b,
0x00000014,0x00000015,0x00000001,0x00040020,0x00000017,0x00000003,0x00000008,0x0003001e,
0x00000019,0x00000007,0x00040020,0x0000001a,0x00000003,0x00000019,0x0004003b,0x0000001a,
0x0000001b,0x00000003,0x00040018,0x0000001c,0x00000007,0x00000004,0x0003001e,0x0000001d,
0x0000001c,0x00040020,0x0000001e,0x00000002,0x0000001d,0x0004003b,0x0000001e,0x0000001f,
0x00000002,0x00040020,0x00000020,0x00000002,0x0000001c,0x0004003b,0x00000014,0x00000023,
0x00000001,0x0004002b,0x00000006,0x00000025,0x00000000,0x0004002b,0x00000006,0x00000026,
0x3f800000,0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,
0x0004003d,0x00000007,0x00000010,0x0000000f,0x00050041,0x00000011,0x00000012,0x0000000b,
0x0000000d,0x0003003e,0x00000012,0x00000010,0x0004003d,0x00000008,0x00000016,0x00000015,
0x00050041,0x00000017,0x00000018,0x0000000b,0x00000013,0x0003003e,0x00000018,0x00000016,
0x00050041,0x00000020,0x00000021,0x0000001f,0x0000000d,0x0004003d,0x0000001c,0x00000022,
0x00000021,0x0004003d,0x00000008,0x00000024,0x00000023,0x00050051,0x00000006,0x00000027,
0x00000024,0x00000000,0x00050051,0x00000006,0x00000028,0x00000024,0x00000001,0x00070050,
0x00000007,0x00000029,0x00000027,0x00000028,0x00000025,0x00000026,0x00050091,0x00000007,
0x0000002a,0x00000022,0x00000029,0x00050041,0x00000011,0x0000002b,0x0000001b,0x0000000d,
0x0003003e,0x0000002b,0x0000002a,0x000100fd,0x00010038
};
// glsl_shader.frag, compiled with:
// # glslangValidator -V -x -o glsl_shader.frag.u32 glsl_shader.frag
/*
#version 450 core
layout(location = 0) out vec4 fColor;
layout(set=0, binding=1) uniform sampler s;
layout(set=1, binding=0) uniform texture2D t;
layout(location = 0) in struct { vec4 Color; vec2 UV; } In;
void main()
{
fColor = In.Color * texture(sampler2D(t, s), In.UV.st);
}
*/
static uint32_t __glsl_shader_frag_spv[] =
{
0x07230203,0x00010000,0x00080007,0x00000023,0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000d,0x00030010,
0x00000004,0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,
0x00000000,0x00040005,0x00000009,0x6c6f4366,0x0000726f,0x00030005,0x0000000b,0x00000000,
0x00050006,0x0000000b,0x00000000,0x6f6c6f43,0x00000072,0x00040006,0x0000000b,0x00000001,
0x00005655,0x00030005,0x0000000d,0x00006e49,0x00030005,0x00000015,0x00000074,0x00030005,
0x00000019,0x00000073,0x00040047,0x00000009,0x0000001e,0x00000000,0x00040047,0x0000000d,
0x0000001e,0x00000000,0x00040047,0x00000015,0x00000022,0x00000001,0x00040047,0x00000015,
0x00000021,0x00000000,0x00040047,0x00000019,0x00000022,0x00000000,0x00040047,0x00000019,
0x00000021,0x00000001,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,
0x00000006,0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,
0x00000003,0x00000007,0x0004003b,0x00000008,0x00000009,0x00000003,0x00040017,0x0000000a,
0x00000006,0x00000002,0x0004001e,0x0000000b,0x00000007,0x0000000a,0x00040020,0x0000000c,
0x00000001,0x0000000b,0x0004003b,0x0000000c,0x0000000d,0x00000001,0x00040015,0x0000000e,
0x00000020,0x00000001,0x0004002b,0x0000000e,0x0000000f,0x00000000,0x00040020,0x00000010,
0x00000001,0x00000007,0x00090019,0x00000013,0x00000006,0x00000001,0x00000000,0x00000000,
0x00000000,0x00000001,0x00000000,0x00040020,0x00000014,0x00000000,0x00000013,0x0004003b,
0x00000014,0x00000015,0x00000000,0x0002001a,0x00000017,0x00040020,0x00000018,0x00000000,
0x00000017,0x0004003b,0x00000018,0x00000019,0x00000000,0x0003001b,0x0000001b,0x00000013,
0x0004002b,0x0000000e,0x0000001d,0x00000001,0x00040020,0x0000001e,0x00000001,0x0000000a,
0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x00050041,
0x00000010,0x00000011,0x0000000d,0x0000000f,0x0004003d,0x00000007,0x00000012,0x00000011,
0x0004003d,0x00000013,0x00000016,0x00000015,0x0004003d,0x00000017,0x0000001a,0x00000019,
0x00050056,0x0000001b,0x0000001c,0x00000016,0x0000001a,0x00050041,0x0000001e,0x0000001f,
0x0000000d,0x0000001d,0x0004003d,0x0000000a,0x00000020,0x0000001f,0x00050057,0x00000007,
0x00000021,0x0000001c,0x00000020,0x00050085,0x00000007,0x00000022,0x00000012,0x00000021,
0x0003003e,0x00000009,0x00000022,0x000100fd,0x00010038
};
static void SafeRelease(ImDrawIdx*& res)
{
if (res)
delete[] res;
res = NULL;
}
static void SafeRelease(ImDrawVert*& res)
{
if (res)
delete[] res;
res = NULL;
}
static void SafeRelease(WGPUBindGroupLayout& res)
{
if (res)
wgpuBindGroupLayoutRelease(res);
res = NULL;
}
static void SafeRelease(WGPUBindGroup& res)
{
if (res)
wgpuBindGroupRelease(res);
res = NULL;
}
static void SafeRelease(WGPUBuffer& res)
{
if (res)
wgpuBufferRelease(res);
res = NULL;
}
static void SafeRelease(WGPURenderPipeline& res)
{
if (res)
wgpuRenderPipelineRelease(res);
res = NULL;
}
static void SafeRelease(WGPUSampler& res)
{
if (res)
wgpuSamplerRelease(res);
res = NULL;
}
static void SafeRelease(WGPUShaderModule& res)
{
if (res)
wgpuShaderModuleRelease(res);
res = NULL;
}
static void SafeRelease(WGPUTextureView& res)
{
if (res)
wgpuTextureViewRelease(res);
res = NULL;
}
static void SafeRelease(WGPUTexture& res)
{
if (res)
wgpuTextureRelease(res);
res = NULL;
}
static void SafeRelease(RenderResources& res)
{
SafeRelease(res.FontTexture);
SafeRelease(res.FontTextureView);
SafeRelease(res.Sampler);
SafeRelease(res.Uniforms);
SafeRelease(res.CommonBindGroup);
SafeRelease(res.ImageBindGroupLayout);
SafeRelease(res.ImageBindGroup);
};
static void SafeRelease(FrameResources& res)
{
SafeRelease(res.IndexBuffer);
SafeRelease(res.VertexBuffer);
SafeRelease(res.IndexBufferHost);
SafeRelease(res.VertexBufferHost);
}
static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(uint32_t* binary_data, uint32_t binary_data_size)
{
WGPUShaderModuleSPIRVDescriptor spirv_desc = {};
spirv_desc.chain.sType = WGPUSType_ShaderModuleSPIRVDescriptor;
spirv_desc.codeSize = binary_data_size;
spirv_desc.code = binary_data;
WGPUShaderModuleDescriptor desc;
desc.nextInChain = reinterpret_cast<WGPUChainedStruct*>(&spirv_desc);
WGPUProgrammableStageDescriptor stage_desc = {};
stage_desc.module = wgpuDeviceCreateShaderModule(g_wgpuDevice, &desc);
stage_desc.entryPoint = "main";
return stage_desc;
}
static WGPUBindGroup ImGui_ImplWGPU_CreateImageBindGroup(WGPUBindGroupLayout layout, WGPUTextureView texture)
{
WGPUBindGroupEntry image_bg_entries[] = { { 0, 0, 0, 0, 0, texture } };
WGPUBindGroupDescriptor image_bg_descriptor = {};
image_bg_descriptor.layout = layout;
image_bg_descriptor.entryCount = sizeof(image_bg_entries) / sizeof(WGPUBindGroupEntry);
image_bg_descriptor.entries = image_bg_entries;
return wgpuDeviceCreateBindGroup(g_wgpuDevice, &image_bg_descriptor);
}
static void ImGui_ImplWGPU_SetupRenderState(ImDrawData* draw_data, WGPURenderPassEncoder ctx, FrameResources* fr)
{
// Setup orthographic projection matrix into our constant buffer
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right).
{
float L = draw_data->DisplayPos.x;
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
float T = draw_data->DisplayPos.y;
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
float mvp[4][4] =
{
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.5f, 0.0f },
{ (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
};
wgpuQueueWriteBuffer(wgpuDeviceGetDefaultQueue(g_wgpuDevice), g_resources.Uniforms, 0, mvp, sizeof(mvp));
}
// Setup viewport
wgpuRenderPassEncoderSetViewport(ctx, 0, 0, draw_data->DisplaySize.x, draw_data->DisplaySize.y, 0, 1);
// Bind shader and vertex buffers
unsigned int stride = sizeof(ImDrawVert);
unsigned int offset = 0;
wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, offset, fr->VertexBufferSize * stride);
wgpuRenderPassEncoderSetIndexBuffer(ctx, fr->IndexBuffer, sizeof(ImDrawIdx) == 2 ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32, 0, fr->IndexBufferSize * sizeof(ImDrawIdx));
wgpuRenderPassEncoderSetPipeline(ctx, g_pipelineState);
wgpuRenderPassEncoderSetBindGroup(ctx, 0, g_resources.CommonBindGroup, 0, NULL);
// Setup blend factor
WGPUColor blend_color = { 0.f, 0.f, 0.f, 0.f };
wgpuRenderPassEncoderSetBlendColor(ctx, &blend_color);
}
// Render function
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder)
{
// Avoid rendering when minimized
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
return;
// FIXME: Assuming that this only gets called once per frame!
// If not, we can't just re-allocate the IB or VB, we'll have to do a proper allocator.
g_frameIndex = g_frameIndex + 1;
FrameResources* fr = &g_pFrameResources[g_frameIndex % g_numFramesInFlight];
// Create and grow vertex/index buffers if needed
if (fr->VertexBuffer == NULL || fr->VertexBufferSize < draw_data->TotalVtxCount)
{
SafeRelease(fr->VertexBuffer);
SafeRelease(fr->VertexBufferHost);
fr->VertexBufferSize = draw_data->TotalVtxCount + 5000;
WGPUBufferDescriptor vb_desc =
{
NULL,
"Dear ImGui Vertex buffer",
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex,
fr->VertexBufferSize * sizeof(ImDrawVert),
false
};
fr->VertexBuffer = wgpuDeviceCreateBuffer(g_wgpuDevice, &vb_desc);
if (!fr->VertexBuffer)
return;
fr->VertexBufferHost = new ImDrawVert[fr->VertexBufferSize];
}
if (fr->IndexBuffer == NULL || fr->IndexBufferSize < draw_data->TotalIdxCount)
{
SafeRelease(fr->IndexBuffer);
SafeRelease(fr->IndexBufferHost);
fr->IndexBufferSize = draw_data->TotalIdxCount + 10000;
WGPUBufferDescriptor ib_desc =
{
NULL,
"Dear ImGui Index buffer",
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index,
fr->IndexBufferSize * sizeof(ImDrawIdx),
false
};
fr->IndexBuffer = wgpuDeviceCreateBuffer(g_wgpuDevice, &ib_desc);
if (!fr->IndexBuffer)
return;
fr->IndexBufferHost = new ImDrawIdx[fr->IndexBufferSize];
}
// Upload vertex/index data into a single contiguous GPU buffer
ImDrawVert* vtx_dst = (ImDrawVert*)fr->VertexBufferHost;
ImDrawIdx* idx_dst = (ImDrawIdx*)fr->IndexBufferHost;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
vtx_dst += cmd_list->VtxBuffer.Size;
idx_dst += cmd_list->IdxBuffer.Size;
}
int64_t vb_write_size = ((char*)vtx_dst - (char*)fr->VertexBufferHost + 3) & ~3;
int64_t ib_write_size = ((char*)idx_dst - (char*)fr->IndexBufferHost + 3) & ~3;
wgpuQueueWriteBuffer(wgpuDeviceGetDefaultQueue(g_wgpuDevice), fr->VertexBuffer, 0, fr->VertexBufferHost, vb_write_size);
wgpuQueueWriteBuffer(wgpuDeviceGetDefaultQueue(g_wgpuDevice), fr->IndexBuffer, 0, fr->IndexBufferHost, ib_write_size);
// Setup desired render state
ImGui_ImplWGPU_SetupRenderState(draw_data, pass_encoder, fr);
// Render command lists
// (Because we merged all buffers into a single one, we maintain our own offset into them)
int global_vtx_offset = 0;
int global_idx_offset = 0;
ImVec2 clip_off = draw_data->DisplayPos;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback != NULL)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplWGPU_SetupRenderState(draw_data, pass_encoder, fr);
else
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
// Bind custom texture
auto bind_group = g_resources.ImageBindGroups.GetVoidPtr(ImHashData(&pcmd->TextureId, sizeof(ImTextureID)));
if (bind_group)
{
wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, (WGPUBindGroup)bind_group, 0, NULL);
}
else
{
WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup(g_resources.ImageBindGroupLayout, (WGPUTextureView)pcmd->TextureId);
g_resources.ImageBindGroups.SetVoidPtr(ImHashData(&pcmd->TextureId, sizeof(ImTextureID)), image_bind_group);
wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, image_bind_group, 0, NULL);
}
// Apply Scissor, Bind texture, Draw
uint32_t clip_rect[4];
clip_rect[0] = static_cast<uint32_t>(pcmd->ClipRect.x - clip_off.x);
clip_rect[1] = static_cast<uint32_t>(pcmd->ClipRect.y - clip_off.y);
clip_rect[2] = static_cast<uint32_t>(pcmd->ClipRect.z - clip_off.x);
clip_rect[3] = static_cast<uint32_t>(pcmd->ClipRect.w - clip_off.y);
wgpuRenderPassEncoderSetScissorRect(pass_encoder, clip_rect[0], clip_rect[1], clip_rect[2] - clip_rect[0], clip_rect[3] - clip_rect[1]);
wgpuRenderPassEncoderDrawIndexed(pass_encoder, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
}
}
global_idx_offset += cmd_list->IdxBuffer.Size;
global_vtx_offset += cmd_list->VtxBuffer.Size;
}
}
static WGPUBuffer ImGui_ImplWGPU_CreateBufferFromData(const WGPUDevice& device, const void* data, uint64_t size, WGPUBufferUsage usage)
{
WGPUBufferDescriptor descriptor = {};
descriptor.size = size;
descriptor.usage = usage | WGPUBufferUsage_CopyDst;
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
WGPUQueue queue = wgpuDeviceGetDefaultQueue(g_wgpuDevice);
wgpuQueueWriteBuffer(queue, buffer, 0, data, size);
return buffer;
}
static void ImGui_ImplWGPU_CreateFontsTexture()
{
// Build texture atlas
ImGuiIO& io = ImGui::GetIO();
unsigned char* pixels;
int width, height, size_pp;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &size_pp);
// Upload texture to graphics system
{
WGPUTextureDescriptor tex_desc = {};
tex_desc.label = "Dear ImGui Font Texture";
tex_desc.dimension = WGPUTextureDimension_2D;
tex_desc.size.width = width;
tex_desc.size.height = height;
tex_desc.size.depth = 1;
tex_desc.sampleCount = 1;
tex_desc.format = WGPUTextureFormat_RGBA8Unorm;
tex_desc.mipLevelCount = 1;
tex_desc.usage = WGPUTextureUsage_CopyDst | WGPUTextureUsage_Sampled;
g_resources.FontTexture = wgpuDeviceCreateTexture(g_wgpuDevice, &tex_desc);
WGPUTextureViewDescriptor tex_view_desc = {};
tex_view_desc.format = WGPUTextureFormat_RGBA8Unorm;
tex_view_desc.dimension = WGPUTextureViewDimension_2D;
tex_view_desc.baseMipLevel = 0;
tex_view_desc.mipLevelCount = 1;
tex_view_desc.baseArrayLayer = 0;
tex_view_desc.arrayLayerCount = 1;
tex_view_desc.aspect = WGPUTextureAspect_All;
g_resources.FontTextureView = wgpuTextureCreateView(g_resources.FontTexture, &tex_view_desc);
}
// Upload texture data
{
WGPUBuffer staging_buffer = ImGui_ImplWGPU_CreateBufferFromData(g_wgpuDevice, pixels, (uint32_t)(width * size_pp * height), WGPUBufferUsage_CopySrc);
WGPUBufferCopyView bufferCopyView = {};
bufferCopyView.buffer = staging_buffer;
bufferCopyView.layout.offset = 0;
bufferCopyView.layout.bytesPerRow = width * size_pp;
bufferCopyView.layout.rowsPerImage = height;
WGPUTextureCopyView textureCopyView = {};
textureCopyView.texture = g_resources.FontTexture;
textureCopyView.mipLevel = 0;
textureCopyView.origin = { 0, 0, 0 };
#if !defined(__EMSCRIPTEN__) || HAS_EMSCRIPTEN_VERSION(2, 0, 14)
textureCopyView.aspect = WGPUTextureAspect_All;
#endif
WGPUExtent3D copySize = { (uint32_t)width, (uint32_t)height, 1 };
WGPUCommandEncoderDescriptor enc_desc = {};
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(g_wgpuDevice, &enc_desc);
wgpuCommandEncoderCopyBufferToTexture(encoder, &bufferCopyView, &textureCopyView, &copySize);
WGPUCommandBufferDescriptor cmd_buf_desc = {};
WGPUCommandBuffer copy = wgpuCommandEncoderFinish(encoder, &cmd_buf_desc);
WGPUQueue queue = wgpuDeviceGetDefaultQueue(g_wgpuDevice);
wgpuQueueSubmit(queue, 1, &copy);
wgpuCommandEncoderRelease(encoder);
wgpuBufferRelease(staging_buffer);
}
// Create the associated sampler
{
WGPUSamplerDescriptor sampler_desc = {};
sampler_desc.minFilter = WGPUFilterMode_Linear;
sampler_desc.magFilter = WGPUFilterMode_Linear;
sampler_desc.mipmapFilter = WGPUFilterMode_Linear;
sampler_desc.addressModeU = WGPUAddressMode_Repeat;
sampler_desc.addressModeV = WGPUAddressMode_Repeat;
sampler_desc.addressModeW = WGPUAddressMode_Repeat;
#if !defined(__EMSCRIPTEN__) || HAS_EMSCRIPTEN_VERSION(2, 0, 14)
sampler_desc.maxAnisotropy = 1;
#endif
g_resources.Sampler = wgpuDeviceCreateSampler(g_wgpuDevice, &sampler_desc);
}
// Store our identifier
static_assert(sizeof(ImTextureID) >= sizeof(g_resources.FontTexture), "Can't pack descriptor handle into TexID, 32-bit not supported yet.");
io.Fonts->SetTexID((ImTextureID)g_resources.FontTextureView);
}
static void ImGui_ImplWGPU_CreateUniformBuffer()
{
WGPUBufferDescriptor ub_desc =
{
NULL,
"Dear ImGui Uniform buffer",
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform,
sizeof(Uniforms),
false
};
g_resources.Uniforms = wgpuDeviceCreateBuffer(g_wgpuDevice, &ub_desc);
}
bool ImGui_ImplWGPU_CreateDeviceObjects()
{
if (!g_wgpuDevice)
return false;
if (g_pipelineState)
ImGui_ImplWGPU_InvalidateDeviceObjects();
// Create render pipeline
WGPURenderPipelineDescriptor graphics_pipeline_desc = {};
graphics_pipeline_desc.primitiveTopology = WGPUPrimitiveTopology_TriangleList;
graphics_pipeline_desc.sampleCount = 1;
graphics_pipeline_desc.sampleMask = UINT_MAX;
WGPUBindGroupLayoutEntry common_bg_layout_entries[2] = {};
common_bg_layout_entries[0].binding = 0;
common_bg_layout_entries[0].visibility = WGPUShaderStage_Vertex;
#if !defined(__EMSCRIPTEN__) || HAS_EMSCRIPTEN_VERSION(2, 0, 14)
common_bg_layout_entries[0].buffer.type = WGPUBufferBindingType_Uniform;
#else
common_bg_layout_entries[0].type = WGPUBindingType_UniformBuffer;
#endif
common_bg_layout_entries[1].binding = 1;
common_bg_layout_entries[1].visibility = WGPUShaderStage_Fragment;
#if !defined(__EMSCRIPTEN__) || HAS_EMSCRIPTEN_VERSION(2, 0, 14)
common_bg_layout_entries[1].sampler.type = WGPUSamplerBindingType_Filtering;
#else
common_bg_layout_entries[1].type = WGPUBindingType_Sampler;
#endif
WGPUBindGroupLayoutEntry image_bg_layout_entries[1] = {};
image_bg_layout_entries[0].binding = 0;
image_bg_layout_entries[0].visibility = WGPUShaderStage_Fragment;
#if !defined(__EMSCRIPTEN__) || HAS_EMSCRIPTEN_VERSION(2, 0, 14)
image_bg_layout_entries[0].texture.sampleType = WGPUTextureSampleType_Float;
image_bg_layout_entries[0].texture.viewDimension = WGPUTextureViewDimension_2D;
#else
image_bg_layout_entries[0].type = WGPUBindingType_SampledTexture;
#endif
WGPUBindGroupLayoutDescriptor common_bg_layout_desc = {};
common_bg_layout_desc.entryCount = 2;
common_bg_layout_desc.entries = common_bg_layout_entries;
WGPUBindGroupLayoutDescriptor image_bg_layout_desc = {};
image_bg_layout_desc.entryCount = 1;
image_bg_layout_desc.entries = image_bg_layout_entries;
WGPUBindGroupLayout bg_layouts[2];
bg_layouts[0] = wgpuDeviceCreateBindGroupLayout(g_wgpuDevice, &common_bg_layout_desc);
bg_layouts[1] = wgpuDeviceCreateBindGroupLayout(g_wgpuDevice, &image_bg_layout_desc);
WGPUPipelineLayoutDescriptor layout_desc = {};
layout_desc.bindGroupLayoutCount = 2;
layout_desc.bindGroupLayouts = bg_layouts;
graphics_pipeline_desc.layout = wgpuDeviceCreatePipelineLayout(g_wgpuDevice, &layout_desc);
// Create the vertex shader
WGPUProgrammableStageDescriptor vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModule(__glsl_shader_vert_spv, sizeof(__glsl_shader_vert_spv) / sizeof(uint32_t));
graphics_pipeline_desc.vertexStage = vertex_shader_desc;
// Vertex input configuration
WGPUVertexAttributeDescriptor attribute_binding_desc[] =
{
{ WGPUVertexFormat_Float2, (uint64_t)IM_OFFSETOF(ImDrawVert, pos), 0 },
{ WGPUVertexFormat_Float2, (uint64_t)IM_OFFSETOF(ImDrawVert, uv), 1 },
{ WGPUVertexFormat_UChar4Norm, (uint64_t)IM_OFFSETOF(ImDrawVert, col), 2 },
};
WGPUVertexBufferLayoutDescriptor buffer_binding_desc;
buffer_binding_desc.arrayStride = sizeof(ImDrawVert);
buffer_binding_desc.stepMode = WGPUInputStepMode_Vertex;
buffer_binding_desc.attributeCount = 3;
buffer_binding_desc.attributes = attribute_binding_desc;
WGPUVertexStateDescriptor vertex_state_desc = {};
vertex_state_desc.indexFormat = WGPUIndexFormat_Undefined;
vertex_state_desc.vertexBufferCount = 1;
vertex_state_desc.vertexBuffers = &buffer_binding_desc;
graphics_pipeline_desc.vertexState = &vertex_state_desc;
// Create the pixel shader
WGPUProgrammableStageDescriptor pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModule(__glsl_shader_frag_spv, sizeof(__glsl_shader_frag_spv) / sizeof(uint32_t));
graphics_pipeline_desc.fragmentStage = &pixel_shader_desc;
// Create the blending setup
WGPUColorStateDescriptor color_state = {};
{
color_state.format = g_renderTargetFormat;
color_state.alphaBlend.operation = WGPUBlendOperation_Add;
color_state.alphaBlend.srcFactor = WGPUBlendFactor_One;
color_state.alphaBlend.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
color_state.colorBlend.operation = WGPUBlendOperation_Add;
color_state.colorBlend.srcFactor = WGPUBlendFactor_SrcAlpha;
color_state.colorBlend.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
color_state.writeMask = WGPUColorWriteMask_All;
graphics_pipeline_desc.colorStateCount = 1;
graphics_pipeline_desc.colorStates = &color_state;
graphics_pipeline_desc.alphaToCoverageEnabled = false;
}
// Create the rasterizer state
WGPURasterizationStateDescriptor raster_desc = {};
{
raster_desc.cullMode = WGPUCullMode_None;
raster_desc.frontFace = WGPUFrontFace_CW;
raster_desc.depthBias = 0;
raster_desc.depthBiasClamp = 0;
raster_desc.depthBiasSlopeScale = 0;
graphics_pipeline_desc.rasterizationState = &raster_desc;
}
// Create depth-stencil State
WGPUDepthStencilStateDescriptor depth_desc = {};
{
// Configure disabled state
depth_desc.format = WGPUTextureFormat_Undefined;
depth_desc.depthWriteEnabled = true;
depth_desc.depthCompare = WGPUCompareFunction_Always;
depth_desc.stencilReadMask = 0;
depth_desc.stencilWriteMask = 0;
depth_desc.stencilBack.compare = WGPUCompareFunction_Always;
depth_desc.stencilBack.failOp = WGPUStencilOperation_Keep;
depth_desc.stencilBack.depthFailOp = WGPUStencilOperation_Keep;
depth_desc.stencilBack.passOp = WGPUStencilOperation_Keep;
depth_desc.stencilFront.compare = WGPUCompareFunction_Always;
depth_desc.stencilFront.failOp = WGPUStencilOperation_Keep;
depth_desc.stencilFront.depthFailOp = WGPUStencilOperation_Keep;
depth_desc.stencilFront.passOp = WGPUStencilOperation_Keep;
// No depth buffer corresponds to no configuration
graphics_pipeline_desc.depthStencilState = NULL;
}
g_pipelineState = wgpuDeviceCreateRenderPipeline(g_wgpuDevice, &graphics_pipeline_desc);
ImGui_ImplWGPU_CreateFontsTexture();
ImGui_ImplWGPU_CreateUniformBuffer();
// Create resource bind group
WGPUBindGroupEntry common_bg_entries[] =
{
{ 0, g_resources.Uniforms, 0, sizeof(Uniforms), 0, 0 },
{ 1, 0, 0, 0, g_resources.Sampler, 0 },
};
WGPUBindGroupDescriptor common_bg_descriptor = {};
common_bg_descriptor.layout = bg_layouts[0];
common_bg_descriptor.entryCount = sizeof(common_bg_entries) / sizeof(WGPUBindGroupEntry);
common_bg_descriptor.entries = common_bg_entries;
g_resources.CommonBindGroup = wgpuDeviceCreateBindGroup(g_wgpuDevice, &common_bg_descriptor);
g_resources.ImageBindGroupLayout = bg_layouts[1];
WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup(bg_layouts[1], g_resources.FontTextureView);
g_resources.ImageBindGroup = image_bind_group;
g_resources.ImageBindGroups.SetVoidPtr(ImHashData(&g_resources.FontTextureView, sizeof(ImTextureID)), image_bind_group);
SafeRelease(vertex_shader_desc.module);
SafeRelease(pixel_shader_desc.module);
SafeRelease(bg_layouts[0]);
return true;
}
void ImGui_ImplWGPU_InvalidateDeviceObjects()
{
if (!g_wgpuDevice)
return;
SafeRelease(g_pipelineState);
SafeRelease(g_resources);
ImGuiIO& io = ImGui::GetIO();
io.Fonts->SetTexID(NULL); // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
for (unsigned int i = 0; i < g_numFramesInFlight; i++)
SafeRelease(g_pFrameResources[i]);
}
bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextureFormat rt_format)
{
// Setup backend capabilities flags
ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = "imgui_impl_webgpu";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
g_wgpuDevice = device;
g_renderTargetFormat = rt_format;
g_pFrameResources = new FrameResources[num_frames_in_flight];
g_numFramesInFlight = num_frames_in_flight;
g_frameIndex = UINT_MAX;
g_resources.FontTexture = NULL;
g_resources.FontTextureView = NULL;
g_resources.Sampler = NULL;
g_resources.Uniforms = NULL;
g_resources.CommonBindGroup = NULL;
g_resources.ImageBindGroupLayout = NULL;
g_resources.ImageBindGroups.Data.reserve(100);
g_resources.ImageBindGroup = NULL;
// Create buffers with a default size (they will later be grown as needed)
for (int i = 0; i < num_frames_in_flight; i++)
{
FrameResources* fr = &g_pFrameResources[i];
fr->IndexBuffer = NULL;
fr->VertexBuffer = NULL;
fr->IndexBufferHost = NULL;
fr->VertexBufferHost = NULL;
fr->IndexBufferSize = 10000;
fr->VertexBufferSize = 5000;
}
return true;
}
void ImGui_ImplWGPU_Shutdown()
{
ImGui_ImplWGPU_InvalidateDeviceObjects();
delete[] g_pFrameResources;
g_pFrameResources = NULL;
g_wgpuDevice = NULL;
g_numFramesInFlight = 0;
g_frameIndex = UINT_MAX;
}
void ImGui_ImplWGPU_NewFrame()
{
if (!g_pipelineState)
ImGui_ImplWGPU_CreateDeviceObjects();
}

View File

@ -0,0 +1,24 @@
// dear imgui: Renderer for WebGPU
// This needs to be used along with a Platform Binding (e.g. GLFW)
// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.)
// Implemented features:
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
#pragma once
#include "imgui.h" // IMGUI_IMPL_API
#include <webgpu/webgpu.h>
IMGUI_IMPL_API bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextureFormat rt_format);
IMGUI_IMPL_API void ImGui_ImplWGPU_Shutdown();
IMGUI_IMPL_API void ImGui_ImplWGPU_NewFrame();
IMGUI_IMPL_API void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder);
// Use if you want to reset your rendering device without losing Dear ImGui state.
IMGUI_IMPL_API void ImGui_ImplWGPU_InvalidateDeviceObjects();
IMGUI_IMPL_API bool ImGui_ImplWGPU_CreateDeviceObjects();

View File

@ -6,7 +6,6 @@
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
@ -19,21 +18,23 @@
#endif
#include <windows.h>
#include <tchar.h>
#include <dwmapi.h>
// Using XInput library for gamepad (with recent Windows SDK this may leads to executables which won't run on Windows 7)
// Configuration flags to add in your imconfig.h file:
//#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD // Disable gamepad support (this used to be meaningful before <1.81) but we know load XInput dynamically so the option is less relevant now.
// Using XInput for gamepad (will load DLL dynamically)
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
#include <XInput.h>
#else
#define IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT
#endif
#if defined(_MSC_VER) && !defined(IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT)
#pragma comment(lib, "xinput")
//#pragma comment(lib, "Xinput9_1_0")
typedef DWORD (WINAPI *PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*);
typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
#endif
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2021-02-18: Added ImGui_ImplWin32_EnableAlphaCompositing(). Non Visual Studio users will need to link with dwmapi.lib (MinGW/gcc: use -ldwmapi).
// 2021-02-17: Fixed ImGui_ImplWin32_EnableDpiAwareness() attempting to get SetProcessDpiAwareness from shcore.dll on Windows 8 whereas it is only supported on Windows 8.1.
// 2021-01-25: Inputs: Dynamically loading XInput DLL.
// 2020-12-04: Misc: Fixed setting of io.DisplaySize to invalid/uninitialized data when after hwnd has been closed.
// 2020-03-03: Inputs: Calling AddInputCharacterUTF16() to support surrogate pairs leading to codepoint >= 0x10000 (for more complete CJK inputs)
// 2020-02-17: Added ImGui_ImplWin32_EnableDpiAwareness(), ImGui_ImplWin32_GetDpiScaleForHwnd(), ImGui_ImplWin32_GetDpiScaleForMonitor() helper functions.
@ -66,12 +67,13 @@ static INT64 g_TicksPerSecond = 0;
static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_COUNT;
static bool g_HasGamepad = false;
static bool g_WantUpdateHasGamepad = true;
static bool g_WantUpdateMonitors = true;
// Forward Declarations
static void ImGui_ImplWin32_InitPlatformInterface();
static void ImGui_ImplWin32_ShutdownPlatformInterface();
static void ImGui_ImplWin32_UpdateMonitors();
// XInput DLL and functions
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
static HMODULE g_XInputDLL = NULL;
static PFN_XInputGetCapabilities g_XInputGetCapabilities = NULL;
static PFN_XInputGetState g_XInputGetState = NULL;
#endif
// Functions
bool ImGui_ImplWin32_Init(void* hwnd)
@ -82,21 +84,14 @@ bool ImGui_ImplWin32_Init(void* hwnd)
return false;
// Setup backend capabilities flags
g_hWnd = (HWND)hwnd;
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can set io.MouseHoveredViewport correctly (optional, not easy)
io.BackendPlatformName = "imgui_impl_win32";
io.ImeWindowHandle = hwnd;
// Our mouse update function expect PlatformHandle to be filled for the main viewport
g_hWnd = (HWND)hwnd;
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
main_viewport->PlatformHandle = main_viewport->PlatformHandleRaw = (void*)g_hWnd;
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplWin32_InitPlatformInterface();
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime.
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime.
io.KeyMap[ImGuiKey_Tab] = VK_TAB;
io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
@ -120,13 +115,46 @@ bool ImGui_ImplWin32_Init(void* hwnd)
io.KeyMap[ImGuiKey_Y] = 'Y';
io.KeyMap[ImGuiKey_Z] = 'Z';
// Dynamically load XInput library
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
const char* xinput_dll_names[] =
{
"xinput1_4.dll", // Windows 8+
"xinput1_3.dll", // DirectX SDK
"xinput9_1_0.dll", // Windows Vista, Windows 7
"xinput1_2.dll", // DirectX SDK
"xinput1_1.dll" // DirectX SDK
};
for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++)
if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n]))
{
g_XInputDLL = dll;
g_XInputGetCapabilities = (PFN_XInputGetCapabilities)::GetProcAddress(dll, "XInputGetCapabilities");
g_XInputGetState = (PFN_XInputGetState)::GetProcAddress(dll, "XInputGetState");
break;
}
#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
return true;
}
void ImGui_ImplWin32_Shutdown()
{
ImGui_ImplWin32_ShutdownPlatformInterface();
g_hWnd = (HWND)0;
// Unload XInput library
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
if (g_XInputDLL)
::FreeLibrary(g_XInputDLL);
g_XInputDLL = NULL;
g_XInputGetCapabilities = NULL;
g_XInputGetState = NULL;
#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
g_hWnd = NULL;
g_Time = 0;
g_TicksPerSecond = 0;
g_LastMouseCursor = ImGuiMouseCursor_COUNT;
g_HasGamepad = false;
g_WantUpdateHasGamepad = true;
}
static bool ImGui_ImplWin32_UpdateMouseCursor()
@ -162,63 +190,25 @@ static bool ImGui_ImplWin32_UpdateMouseCursor()
return true;
}
// This code supports multi-viewports (multiple OS Windows mapped into different Dear ImGui viewports)
// Because of that, it is a little more complicated than your typical single-viewport binding code!
static void ImGui_ImplWin32_UpdateMousePos()
{
ImGuiIO& io = ImGui::GetIO();
// Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
// (When multi-viewports are enabled, all imgui positions are same as OS positions)
if (io.WantSetMousePos)
{
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
if ((io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) != 0 || ::ClientToScreen(g_hWnd, &pos))
::ClientToScreen(g_hWnd, &pos);
::SetCursorPos(pos.x, pos.y);
if (::ClientToScreen(g_hWnd, &pos))
::SetCursorPos(pos.x, pos.y);
}
// Set mouse position
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
io.MouseHoveredViewport = 0;
// Set imgui mouse position
POINT mouse_screen_pos;
if (!::GetCursorPos(&mouse_screen_pos))
return;
if (HWND focused_hwnd = ::GetForegroundWindow())
{
if (::IsChild(focused_hwnd, g_hWnd))
focused_hwnd = g_hWnd;
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
// Multi-viewport mode: mouse position in OS absolute coordinates (io.MousePos is (0,0) when the mouse is on the upper-left of the primary monitor)
// This is the position you can get with GetCursorPos(). In theory adding viewport->Pos is also the reverse operation of doing ScreenToClient().
if (ImGui::FindViewportByPlatformHandle((void*)focused_hwnd) != NULL)
io.MousePos = ImVec2((float)mouse_screen_pos.x, (float)mouse_screen_pos.y);
}
else
{
// Single viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window.)
// This is the position you can get with GetCursorPos() + ScreenToClient() or from WM_MOUSEMOVE.
if (focused_hwnd == g_hWnd)
{
POINT mouse_client_pos = mouse_screen_pos;
::ScreenToClient(focused_hwnd, &mouse_client_pos);
io.MousePos = ImVec2((float)mouse_client_pos.x, (float)mouse_client_pos.y);
}
}
}
// (Optional) When using multiple viewports: set io.MouseHoveredViewport to the viewport the OS mouse cursor is hovering.
// Important: this information is not easy to provide and many high-level windowing library won't be able to provide it correctly, because
// - This is _ignoring_ viewports with the ImGuiViewportFlags_NoInputs flag (pass-through windows).
// - This is _regardless_ of whether another viewport is focused or being dragged from.
// If ImGuiBackendFlags_HasMouseHoveredViewport is not set by the backend, imgui will ignore this field and infer the information by relying on the
// rectangles and last focused time of every viewports it knows about. It will be unaware of foreign windows that may be sitting between or over your windows.
if (HWND hovered_hwnd = ::WindowFromPoint(mouse_screen_pos))
if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle((void*)hovered_hwnd))
if ((viewport->Flags & ImGuiViewportFlags_NoInputs) == 0) // FIXME: We still get our NoInputs window with WM_NCHITTEST/HTTRANSPARENT code when decorated?
io.MouseHoveredViewport = viewport->ID;
POINT pos;
if (HWND active_window = ::GetForegroundWindow())
if (active_window == g_hWnd || ::IsChild(active_window, g_hWnd))
if (::GetCursorPos(&pos) && ::ScreenToClient(g_hWnd, &pos))
io.MousePos = ImVec2((float)pos.x, (float)pos.y);
}
// Gamepad navigation mapping
@ -235,13 +225,13 @@ static void ImGui_ImplWin32_UpdateGamepads()
if (g_WantUpdateHasGamepad)
{
XINPUT_CAPABILITIES caps;
g_HasGamepad = (XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS);
g_HasGamepad = g_XInputGetCapabilities ? (g_XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false;
g_WantUpdateHasGamepad = false;
}
XINPUT_STATE xinput_state;
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
if (g_HasGamepad && XInputGetState(0, &xinput_state) == ERROR_SUCCESS)
XINPUT_STATE xinput_state;
if (g_HasGamepad && g_XInputGetState && g_XInputGetState(0, &xinput_state) == ERROR_SUCCESS)
{
const XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
@ -270,33 +260,6 @@ static void ImGui_ImplWin32_UpdateGamepads()
#endif // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
}
static BOOL CALLBACK ImGui_ImplWin32_UpdateMonitors_EnumFunc(HMONITOR monitor, HDC, LPRECT, LPARAM)
{
MONITORINFO info = { 0 };
info.cbSize = sizeof(MONITORINFO);
if (!::GetMonitorInfo(monitor, &info))
return TRUE;
ImGuiPlatformMonitor imgui_monitor;
imgui_monitor.MainPos = ImVec2((float)info.rcMonitor.left, (float)info.rcMonitor.top);
imgui_monitor.MainSize = ImVec2((float)(info.rcMonitor.right - info.rcMonitor.left), (float)(info.rcMonitor.bottom - info.rcMonitor.top));
imgui_monitor.WorkPos = ImVec2((float)info.rcWork.left, (float)info.rcWork.top);
imgui_monitor.WorkSize = ImVec2((float)(info.rcWork.right - info.rcWork.left), (float)(info.rcWork.bottom - info.rcWork.top));
imgui_monitor.DpiScale = ImGui_ImplWin32_GetDpiScaleForMonitor(monitor);
ImGuiPlatformIO& io = ImGui::GetPlatformIO();
if (info.dwFlags & MONITORINFOF_PRIMARY)
io.Monitors.push_front(imgui_monitor);
else
io.Monitors.push_back(imgui_monitor);
return TRUE;
}
static void ImGui_ImplWin32_UpdateMonitors()
{
ImGui::GetPlatformIO().Monitors.resize(0);
::EnumDisplayMonitors(NULL, NULL, ImGui_ImplWin32_UpdateMonitors_EnumFunc, NULL);
g_WantUpdateMonitors = false;
}
void ImGui_ImplWin32_NewFrame()
{
ImGuiIO& io = ImGui::GetIO();
@ -306,8 +269,6 @@ void ImGui_ImplWin32_NewFrame()
RECT rect = { 0, 0, 0, 0 };
::GetClientRect(g_hWnd, &rect);
io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
if (g_WantUpdateMonitors)
ImGui_ImplWin32_UpdateMonitors();
// Setup time step
INT64 current_time = 0;
@ -424,9 +385,6 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
if ((UINT)wParam == DBT_DEVNODES_CHANGED)
g_WantUpdateHasGamepad = true;
return 0;
case WM_DISPLAYCHANGE:
g_WantUpdateMonitors = true;
return 0;
}
return 0;
}
@ -457,7 +415,9 @@ static BOOL IsWindowsVersionOrGreater(WORD major, WORD minor, WORD sp)
cond = ::VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
return ::VerifyVersionInfoW(&osvi, mask, cond);
}
#define IsWindows8Point1OrGreater() IsWindowsVersionOrGreater(HIBYTE(0x0602), LOBYTE(0x0602), 0) // _WIN32_WINNT_WINBLUE
#define IsWindowsVistaOrGreater() IsWindowsVersionOrGreater(HIBYTE(0x0600), LOBYTE(0x0600), 0) // _WIN32_WINNT_VISTA
#define IsWindows8OrGreater() IsWindowsVersionOrGreater(HIBYTE(0x0602), LOBYTE(0x0602), 0) // _WIN32_WINNT_WIN8
#define IsWindows8Point1OrGreater() IsWindowsVersionOrGreater(HIBYTE(0x0603), LOBYTE(0x0603), 0) // _WIN32_WINNT_WINBLUE
#endif
#ifndef DPI_ENUMS_DECLARED
@ -478,9 +438,6 @@ typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_SetThreadDpiAwarenessContext)(DPI_AWAR
// Helper function to enable DPI awareness without setting up a manifest
void ImGui_ImplWin32_EnableDpiAwareness()
{
// Make sure monitors will be updated with latest correct scaling
g_WantUpdateMonitors = true;
// if (IsWindows10OrGreater()) // This needs a manifest to succeed. Instead we try to grab the function pointer!
{
static HINSTANCE user32_dll = ::LoadLibraryA("user32.dll"); // Reference counted per-process
@ -505,7 +462,7 @@ void ImGui_ImplWin32_EnableDpiAwareness()
}
#if defined(_MSC_VER) && !defined(NOGDI)
#pragma comment(lib, "gdi32") // Link with gdi32.lib for GetDeviceCaps()
#pragma comment(lib, "gdi32") // Link with gdi32.lib for GetDeviceCaps(). MinGW will require linking with '-lgdi32'
#endif
float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor)
@ -537,353 +494,44 @@ float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd)
return ImGui_ImplWin32_GetDpiScaleForMonitor(monitor);
}
//--------------------------------------------------------------------------------------------------------
// IME (Input Method Editor) basic support for e.g. Asian language users
//---------------------------------------------------------------------------------------------------------
// Transparency related helpers (optional)
//--------------------------------------------------------------------------------------------------------
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) // UWP doesn't have Win32 functions
#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
#if defined(_MSC_VER)
#pragma comment(lib, "dwmapi") // Link with dwmapi.lib. MinGW will require linking with '-ldwmapi'
#endif
#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(__GNUC__)
#define HAS_WIN32_IME 1
#include <imm.h>
#ifdef _MSC_VER
#pragma comment(lib, "imm32")
#endif
static void ImGui_ImplWin32_SetImeInputPos(ImGuiViewport* viewport, ImVec2 pos)
// [experimental]
// Borrowed from GLFW's function updateFramebufferTransparency() in src/win32_window.c
// (the Dwm* functions are Vista era functions but we are borrowing logic from GLFW)
void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd)
{
COMPOSITIONFORM cf = { CFS_FORCE_POSITION,{ (LONG)(pos.x - viewport->Pos.x), (LONG)(pos.y - viewport->Pos.y) },{ 0, 0, 0, 0 } };
if (HWND hwnd = (HWND)viewport->PlatformHandle)
if (HIMC himc = ::ImmGetContext(hwnd))
{
::ImmSetCompositionWindow(himc, &cf);
::ImmReleaseContext(hwnd, himc);
}
}
#else
#define HAS_WIN32_IME 0
#endif
if (!IsWindowsVistaOrGreater())
return;
//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------
BOOL composition;
if (FAILED(::DwmIsCompositionEnabled(&composition)) || !composition)
return;
// Helper structure we store in the void* RenderUserData field of each ImGuiViewport to easily retrieve our backend data.
struct ImGuiViewportDataWin32
{
HWND Hwnd;
bool HwndOwned;
DWORD DwStyle;
DWORD DwExStyle;
ImGuiViewportDataWin32() { Hwnd = NULL; HwndOwned = false; DwStyle = DwExStyle = 0; }
~ImGuiViewportDataWin32() { IM_ASSERT(Hwnd == NULL); }
};
static void ImGui_ImplWin32_GetWin32StyleFromViewportFlags(ImGuiViewportFlags flags, DWORD* out_style, DWORD* out_ex_style)
{
if (flags & ImGuiViewportFlags_NoDecoration)
*out_style = WS_POPUP;
else
*out_style = WS_OVERLAPPEDWINDOW;
if (flags & ImGuiViewportFlags_NoTaskBarIcon)
*out_ex_style = WS_EX_TOOLWINDOW;
else
*out_ex_style = WS_EX_APPWINDOW;
if (flags & ImGuiViewportFlags_TopMost)
*out_ex_style |= WS_EX_TOPMOST;
}
static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport)
{
ImGuiViewportDataWin32* data = IM_NEW(ImGuiViewportDataWin32)();
viewport->PlatformUserData = data;
// Select style and parent window
ImGui_ImplWin32_GetWin32StyleFromViewportFlags(viewport->Flags, &data->DwStyle, &data->DwExStyle);
HWND parent_window = NULL;
if (viewport->ParentViewportId != 0)
if (ImGuiViewport* parent_viewport = ImGui::FindViewportByID(viewport->ParentViewportId))
parent_window = (HWND)parent_viewport->PlatformHandle;
// Create window
RECT rect = { (LONG)viewport->Pos.x, (LONG)viewport->Pos.y, (LONG)(viewport->Pos.x + viewport->Size.x), (LONG)(viewport->Pos.y + viewport->Size.y) };
::AdjustWindowRectEx(&rect, data->DwStyle, FALSE, data->DwExStyle);
data->Hwnd = ::CreateWindowEx(
data->DwExStyle, _T("ImGui Platform"), _T("Untitled"), data->DwStyle, // Style, class name, window name
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, // Window area
parent_window, NULL, ::GetModuleHandle(NULL), NULL); // Parent window, Menu, Instance, Param
data->HwndOwned = true;
viewport->PlatformRequestResize = false;
viewport->PlatformHandle = viewport->PlatformHandleRaw = data->Hwnd;
}
static void ImGui_ImplWin32_DestroyWindow(ImGuiViewport* viewport)
{
if (ImGuiViewportDataWin32* data = (ImGuiViewportDataWin32*)viewport->PlatformUserData)
BOOL opaque;
DWORD color;
if (IsWindows8OrGreater() || (SUCCEEDED(::DwmGetColorizationColor(&color, &opaque)) && !opaque))
{
if (::GetCapture() == data->Hwnd)
{
// Transfer capture so if we started dragging from a window that later disappears, we'll still receive the MOUSEUP event.
::ReleaseCapture();
::SetCapture(g_hWnd);
}
if (data->Hwnd && data->HwndOwned)
::DestroyWindow(data->Hwnd);
data->Hwnd = NULL;
IM_DELETE(data);
}
viewport->PlatformUserData = viewport->PlatformHandle = NULL;
}
static void ImGui_ImplWin32_ShowWindow(ImGuiViewport* viewport)
{
ImGuiViewportDataWin32* data = (ImGuiViewportDataWin32*)viewport->PlatformUserData;
IM_ASSERT(data->Hwnd != 0);
if (viewport->Flags & ImGuiViewportFlags_NoFocusOnAppearing)
::ShowWindow(data->Hwnd, SW_SHOWNA);
else
::ShowWindow(data->Hwnd, SW_SHOW);
}
static void ImGui_ImplWin32_UpdateWindow(ImGuiViewport* viewport)
{
// (Optional) Update Win32 style if it changed _after_ creation.
// Generally they won't change unless configuration flags are changed, but advanced uses (such as manually rewriting viewport flags) make this useful.
ImGuiViewportDataWin32* data = (ImGuiViewportDataWin32*)viewport->PlatformUserData;
IM_ASSERT(data->Hwnd != 0);
DWORD new_style;
DWORD new_ex_style;
ImGui_ImplWin32_GetWin32StyleFromViewportFlags(viewport->Flags, &new_style, &new_ex_style);
// Only reapply the flags that have been changed from our point of view (as other flags are being modified by Windows)
if (data->DwStyle != new_style || data->DwExStyle != new_ex_style)
{
// (Optional) Update TopMost state if it changed _after_ creation
bool top_most_changed = (data->DwExStyle & WS_EX_TOPMOST) != (new_ex_style & WS_EX_TOPMOST);
HWND insert_after = top_most_changed ? ((viewport->Flags & ImGuiViewportFlags_TopMost) ? HWND_TOPMOST : HWND_NOTOPMOST) : 0;
UINT swp_flag = top_most_changed ? 0 : SWP_NOZORDER;
// Apply flags and position (since it is affected by flags)
data->DwStyle = new_style;
data->DwExStyle = new_ex_style;
::SetWindowLong(data->Hwnd, GWL_STYLE, data->DwStyle);
::SetWindowLong(data->Hwnd, GWL_EXSTYLE, data->DwExStyle);
RECT rect = { (LONG)viewport->Pos.x, (LONG)viewport->Pos.y, (LONG)(viewport->Pos.x + viewport->Size.x), (LONG)(viewport->Pos.y + viewport->Size.y) };
::AdjustWindowRectEx(&rect, data->DwStyle, FALSE, data->DwExStyle); // Client to Screen
::SetWindowPos(data->Hwnd, insert_after, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, swp_flag | SWP_NOACTIVATE | SWP_FRAMECHANGED);
::ShowWindow(data->Hwnd, SW_SHOWNA); // This is necessary when we alter the style
viewport->PlatformRequestMove = viewport->PlatformRequestResize = true;
}
}
static ImVec2 ImGui_ImplWin32_GetWindowPos(ImGuiViewport* viewport)
{
ImGuiViewportDataWin32* data = (ImGuiViewportDataWin32*)viewport->PlatformUserData;
IM_ASSERT(data->Hwnd != 0);
POINT pos = { 0, 0 };
::ClientToScreen(data->Hwnd, &pos);
return ImVec2((float)pos.x, (float)pos.y);
}
static void ImGui_ImplWin32_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos)
{
ImGuiViewportDataWin32* data = (ImGuiViewportDataWin32*)viewport->PlatformUserData;
IM_ASSERT(data->Hwnd != 0);
RECT rect = { (LONG)pos.x, (LONG)pos.y, (LONG)pos.x, (LONG)pos.y };
::AdjustWindowRectEx(&rect, data->DwStyle, FALSE, data->DwExStyle);
::SetWindowPos(data->Hwnd, NULL, rect.left, rect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
}
static ImVec2 ImGui_ImplWin32_GetWindowSize(ImGuiViewport* viewport)
{
ImGuiViewportDataWin32* data = (ImGuiViewportDataWin32*)viewport->PlatformUserData;
IM_ASSERT(data->Hwnd != 0);
RECT rect;
::GetClientRect(data->Hwnd, &rect);
return ImVec2(float(rect.right - rect.left), float(rect.bottom - rect.top));
}
static void ImGui_ImplWin32_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
{
ImGuiViewportDataWin32* data = (ImGuiViewportDataWin32*)viewport->PlatformUserData;
IM_ASSERT(data->Hwnd != 0);
RECT rect = { 0, 0, (LONG)size.x, (LONG)size.y };
::AdjustWindowRectEx(&rect, data->DwStyle, FALSE, data->DwExStyle); // Client to Screen
::SetWindowPos(data->Hwnd, NULL, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
}
static void ImGui_ImplWin32_SetWindowFocus(ImGuiViewport* viewport)
{
ImGuiViewportDataWin32* data = (ImGuiViewportDataWin32*)viewport->PlatformUserData;
IM_ASSERT(data->Hwnd != 0);
::BringWindowToTop(data->Hwnd);
::SetForegroundWindow(data->Hwnd);
::SetFocus(data->Hwnd);
}
static bool ImGui_ImplWin32_GetWindowFocus(ImGuiViewport* viewport)
{
ImGuiViewportDataWin32* data = (ImGuiViewportDataWin32*)viewport->PlatformUserData;
IM_ASSERT(data->Hwnd != 0);
return ::GetForegroundWindow() == data->Hwnd;
}
static bool ImGui_ImplWin32_GetWindowMinimized(ImGuiViewport* viewport)
{
ImGuiViewportDataWin32* data = (ImGuiViewportDataWin32*)viewport->PlatformUserData;
IM_ASSERT(data->Hwnd != 0);
return ::IsIconic(data->Hwnd) != 0;
}
static void ImGui_ImplWin32_SetWindowTitle(ImGuiViewport* viewport, const char* title)
{
// ::SetWindowTextA() doesn't properly handle UTF-8 so we explicitely convert our string.
ImGuiViewportDataWin32* data = (ImGuiViewportDataWin32*)viewport->PlatformUserData;
IM_ASSERT(data->Hwnd != 0);
int n = ::MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0);
ImVector<wchar_t> title_w;
title_w.resize(n);
::MultiByteToWideChar(CP_UTF8, 0, title, -1, title_w.Data, n);
::SetWindowTextW(data->Hwnd, title_w.Data);
}
static void ImGui_ImplWin32_SetWindowAlpha(ImGuiViewport* viewport, float alpha)
{
ImGuiViewportDataWin32* data = (ImGuiViewportDataWin32*)viewport->PlatformUserData;
IM_ASSERT(data->Hwnd != 0);
IM_ASSERT(alpha >= 0.0f && alpha <= 1.0f);
if (alpha < 1.0f)
{
DWORD style = ::GetWindowLongW(data->Hwnd, GWL_EXSTYLE) | WS_EX_LAYERED;
::SetWindowLongW(data->Hwnd, GWL_EXSTYLE, style);
::SetLayeredWindowAttributes(data->Hwnd, 0, (BYTE)(255 * alpha), LWA_ALPHA);
HRGN region = ::CreateRectRgn(0, 0, -1, -1);
DWM_BLURBEHIND bb = {};
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
bb.hRgnBlur = region;
bb.fEnable = TRUE;
::DwmEnableBlurBehindWindow((HWND)hwnd, &bb);
::DeleteObject(region);
}
else
{
DWORD style = ::GetWindowLongW(data->Hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED;
::SetWindowLongW(data->Hwnd, GWL_EXSTYLE, style);
DWM_BLURBEHIND bb = {};
bb.dwFlags = DWM_BB_ENABLE;
::DwmEnableBlurBehindWindow((HWND)hwnd, &bb);
}
}
static float ImGui_ImplWin32_GetWindowDpiScale(ImGuiViewport* viewport)
{
ImGuiViewportDataWin32* data = (ImGuiViewportDataWin32*)viewport->PlatformUserData;
IM_ASSERT(data->Hwnd != 0);
return ImGui_ImplWin32_GetDpiScaleForHwnd(data->Hwnd);
}
// FIXME-DPI: Testing DPI related ideas
static void ImGui_ImplWin32_OnChangedViewport(ImGuiViewport* viewport)
{
(void)viewport;
#if 0
ImGuiStyle default_style;
//default_style.WindowPadding = ImVec2(0, 0);
//default_style.WindowBorderSize = 0.0f;
//default_style.ItemSpacing.y = 3.0f;
//default_style.FramePadding = ImVec2(0, 0);
default_style.ScaleAllSizes(viewport->DpiScale);
ImGuiStyle& style = ImGui::GetStyle();
style = default_style;
#endif
}
static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
return true;
if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle((void*)hWnd))
{
switch (msg)
{
case WM_CLOSE:
viewport->PlatformRequestClose = true;
return 0;
case WM_MOVE:
viewport->PlatformRequestMove = true;
break;
case WM_SIZE:
viewport->PlatformRequestResize = true;
break;
case WM_MOUSEACTIVATE:
if (viewport->Flags & ImGuiViewportFlags_NoFocusOnClick)
return MA_NOACTIVATE;
break;
case WM_NCHITTEST:
// Let mouse pass-through the window. This will allow the backend to set io.MouseHoveredViewport properly (which is OPTIONAL).
// The ImGuiViewportFlags_NoInputs flag is set while dragging a viewport, as want to detect the window behind the one we are dragging.
// If you cannot easily access those viewport flags from your windowing/event code: you may manually synchronize its state e.g. in
// your main loop after calling UpdatePlatformWindows(). Iterate all viewports/platform windows and pass the flag to your windowing system.
if (viewport->Flags & ImGuiViewportFlags_NoInputs)
return HTTRANSPARENT;
break;
}
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
static void ImGui_ImplWin32_InitPlatformInterface()
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = ImGui_ImplWin32_WndProcHandler_PlatformWindow;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = ::GetModuleHandle(NULL);
wcex.hIcon = NULL;
wcex.hCursor = NULL;
wcex.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = _T("ImGui Platform");
wcex.hIconSm = NULL;
::RegisterClassEx(&wcex);
ImGui_ImplWin32_UpdateMonitors();
// Register platform interface (will be coupled with a renderer interface)
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Platform_CreateWindow = ImGui_ImplWin32_CreateWindow;
platform_io.Platform_DestroyWindow = ImGui_ImplWin32_DestroyWindow;
platform_io.Platform_ShowWindow = ImGui_ImplWin32_ShowWindow;
platform_io.Platform_SetWindowPos = ImGui_ImplWin32_SetWindowPos;
platform_io.Platform_GetWindowPos = ImGui_ImplWin32_GetWindowPos;
platform_io.Platform_SetWindowSize = ImGui_ImplWin32_SetWindowSize;
platform_io.Platform_GetWindowSize = ImGui_ImplWin32_GetWindowSize;
platform_io.Platform_SetWindowFocus = ImGui_ImplWin32_SetWindowFocus;
platform_io.Platform_GetWindowFocus = ImGui_ImplWin32_GetWindowFocus;
platform_io.Platform_GetWindowMinimized = ImGui_ImplWin32_GetWindowMinimized;
platform_io.Platform_SetWindowTitle = ImGui_ImplWin32_SetWindowTitle;
platform_io.Platform_SetWindowAlpha = ImGui_ImplWin32_SetWindowAlpha;
platform_io.Platform_UpdateWindow = ImGui_ImplWin32_UpdateWindow;
platform_io.Platform_GetWindowDpiScale = ImGui_ImplWin32_GetWindowDpiScale; // FIXME-DPI
platform_io.Platform_OnChangedViewport = ImGui_ImplWin32_OnChangedViewport; // FIXME-DPI
#if HAS_WIN32_IME
platform_io.Platform_SetImeInputPos = ImGui_ImplWin32_SetImeInputPos;
#endif
// Register main window handle (which is owned by the main application, not by us)
// This is mostly for simplicity and consistency, so that our code (e.g. mouse handling etc.) can use same logic for main and secondary viewports.
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
ImGuiViewportDataWin32* data = IM_NEW(ImGuiViewportDataWin32)();
data->Hwnd = g_hWnd;
data->HwndOwned = false;
main_viewport->PlatformUserData = data;
main_viewport->PlatformHandle = (void*)g_hWnd;
}
static void ImGui_ImplWin32_ShutdownPlatformInterface()
{
::UnregisterClass(_T("ImGui Platform"), ::GetModuleHandle(NULL));
}
//---------------------------------------------------------------------------------------------------------

View File

@ -6,7 +6,6 @@
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
@ -19,11 +18,6 @@ IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
// Configuration
// - Disable gamepad support or linking with xinput.lib
//#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
//#define IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT
// Win32 message handler your application need to call.
// - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on <windows.h> from this helper.
// - You should COPY the line below into your .cpp code to forward declare the function and then you can call it.
@ -40,3 +34,8 @@ extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg
IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness();
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor
// Transparency related helpers (optional) [experimental]
// - Use to enable alpha compositing transparency with the desktop.
// - Use together with e.g. clearing your framebuffer with zero-alpha.
IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd

View File

@ -9,13 +9,13 @@ your application or engine to easily integrate Dear ImGui.** Each backend is typ
e.g. Windows ([imgui_impl_win32.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_win32.cpp)), GLFW ([imgui_impl_glfw.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_glfw.cpp)), SDL2 ([imgui_impl_sdl.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_sdl.cpp)), etc.
- The 'Renderer' backends are in charge of: creating atlas texture, rendering imgui draw data.<BR>
e.g. DirectX11 ([imgui_impl_dx11.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_dx11.cpp)), OpenGL/WebGL ([imgui_impl_opengl3.cpp]((https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_opengl3.cpp)), Vulkan ([imgui_impl_vulkan.cpp]((https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_vulkan.cpp)), etc.
e.g. DirectX11 ([imgui_impl_dx11.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_dx11.cpp)), OpenGL/WebGL ([imgui_impl_opengl3.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_opengl3.cpp), Vulkan ([imgui_impl_vulkan.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_vulkan.cpp), etc.
- For some high-level frameworks, a single backend usually handle both 'Platform' and 'Renderer' parts.<BR>
e.g. Allegro 5 ([imgui_impl_allegro5.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_allegro5.cpp)), Marmalade ([imgui_impl_marmalade.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_marmalade.cpp)). If you end up creating a custom backend for your engine, you may want to do the same.
An application usually combines 1 Platform backend + 1 Renderer backend + main Dear ImGui sources.
For example, the [example_win32_directx11](https://github.com/ocornut/imgui/tree/master/examples/example_win32_directx11) application combines imgui_impl_win32.cpp + imgui_impl_dx11.cpp. See [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) for details.
For example, the [example_win32_directx11](https://github.com/ocornut/imgui/tree/master/examples/example_win32_directx11) application combines imgui_impl_win32.cpp + imgui_impl_dx11.cpp. There are 20+ examples in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder. See [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) for details.
### What are backends
@ -36,7 +36,7 @@ Dear ImGui is highly portable and only requires a few things to run and render,
- Optional: multi-viewports support.
etc.
This is essentially what each backends are doing + obligatory portability cruft.
This is essentially what each backends are doing + obligatory portability cruft. Using default backends ensure you can get all those features including the ones that would be harder to implement on your side (e.g. multi-viewports support).
It is important to understand the difference between the core Dear ImGui library (files in the root folder)
and backends which we are describing here (backends/ folder).
@ -46,17 +46,23 @@ and backends which we are describing here (backends/ folder).
e.g. you can get creative and use software rendering or render remotely on a different machine.
### Integrating a backend
See "Getting Started" section of [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) for more details.
### List of backends
In the [backends/](https://github.com/ocornut/imgui/blob/master/backends) folder:
List of Platforms Backends:
imgui_impl_android.cpp ; Android native app API
imgui_impl_glfw.cpp ; GLFW (Windows, macOS, Linux, etc.) http://www.glfw.org/
imgui_impl_osx.mm ; macOS native API (not as feature complete as glfw/sdl backends)
imgui_impl_sdl.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org
imgui_impl_win32.cpp ; Win32 native API (Windows)
imgui_impl_glut.cpp ; GLUT/FreeGLUT (absolutely not recommended in 2020!)
imgui_impl_glut.cpp ; GLUT/FreeGLUT (this is prehistoric software and absolutely not recommended today!)
List of Renderer Backends:
@ -68,6 +74,7 @@ List of Renderer Backends:
imgui_impl_opengl2.cpp ; OpenGL 2 (legacy, fixed pipeline <- don't use with modern OpenGL context)
imgui_impl_opengl3.cpp ; OpenGL 3/4, OpenGL ES 2, OpenGL ES 3 (modern programmable pipeline)
imgui_impl_vulkan.cpp ; Vulkan
imgui_impl_wgpu.cpp ; WebGPU
List of high-level Frameworks Backends (combining Platform + Renderer):
@ -79,35 +86,7 @@ The [example_emscripten_opengl3](https://github.com/ocornut/imgui/tree/master/ex
### Backends for third-party frameworks, graphics API or other languages
See https://github.com/ocornut/imgui/wiki/Bindings
- AGS/Adventure Game Studio
- Amethyst
- bsf
- Cinder
- Cocos2d-x
- Diligent Engine
- Flexium,
- GML/Game Maker Studio2
- GTK3+OpenGL3
- Irrlicht Engine
- LÖVE+LUA
- Magnum
- NanoRT
- Nim Game Lib,
- Ogre
- openFrameworks
- OSG/OpenSceneGraph
- Orx
- px_render
- Qt/QtDirect3D
- SFML
- Sokol
- Unity
- Unreal Engine 4
- vtk
- Win32 GDI
etc.
See https://github.com/ocornut/imgui/wiki/Bindings for the full list.
### Recommended Backends

View File

@ -5,11 +5,11 @@ This document holds the user-facing changelog that we also use in release notes.
We generally fold multiple commits pertaining to the same topic as a single entry.
Changes to backends are also included within the individual .cpp files of each backend.
RELEASE NOTES: https://github.com/ocornut/imgui/releases
REPORT ISSUES, ASK QUESTIONS: https://github.com/ocornut/imgui/issues
COMMITS HISTORY: https://github.com/ocornut/imgui/commits/master
FAQ https://www.dearimgui.org/faq/
WIKI https://github.com/ocornut/imgui/wiki
RELEASE NOTES: https://github.com/ocornut/imgui/releases
REPORT ISSUES: https://github.com/ocornut/imgui/issues
DISCUSS, ASK QUESTIONS: https://github.com/ocornut/imgui/discussions
FAQ https://www.dearimgui.org/faq/
WIKI https://github.com/ocornut/imgui/wiki
WHEN TO UPDATE?
@ -32,83 +32,188 @@ HOW TO UPDATE?
-----------------------------------------------------------------------
DOCKING+MULTI-VIEWPORT BRANCH (In Progress)
-----------------------------------------------------------------------
DOCKING FEATURES
- Added Docking system: [BETA] (#2109, #351)
- Added ImGuiConfigFlags_DockingEnable flag to enable Docking.
Set with `io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;`.
- Added DockSpace(), DockSpaceOverViewport() API.
- Added ImGuiDockNodeFlags flags for DockSpace().
- Added SetNextWindowDockID(), SetNextWindowClass() API.
- Added GetWindowDockID(), IsWindowDocked() API.
- Added ImGuiWindowFlags_NoDocking window flag to disable the possibility for a window to be docked.
Popup, Menu and Child windows always have the ImGuiWindowFlags_NoDocking flag set.
- Added ImGuiWindowClass to specify advanced docking/viewport related flags via SetNextWindowClass().
- Added io.ConfigDockingNoSplit option.
- Added io.ConfigDockingWithShift option.
- Added io.ConfigDockingAlwaysTabBar option.
- Added io.ConfigDockingTransparentPayload option.
- Style: Added ImGuiCol_DockingPreview, ImGuiCol_DockingEmptyBg colors.
- Demo: Added "DockSpace" example app showcasing use of explicit dockspace nodes.
MULTI-VIEWPORT FEATURES (was previously 'viewport' branch, merged into 'docking')
Breaking Changes:
- IMPORTANT: When multi-viewports are enabled (with io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable),
all coordinates/positions will be in your natural OS coordinates space. It means that:
- Reference to hard-coded positions such as in SetNextWindowPos(ImVec2(0,0)) are _probably_ not what you want anymore.
Use GetMainViewport()->Pos to offset hard-coded positions, e.g. SetNextWindowPos(GetMainViewport()->Pos).
- Likewise io.MousePos and GetMousePos() will use OS coordinates.
If you query mouse positions to interact with non-imgui coordinates you will need to offset them.
e.g. subtract GetWindowViewport()->Pos.
- Render function: the ImDrawData structure now contains 'DisplayPos' and 'DisplaySize' fields.
To support multi-viewport, you need to use those values when creating your orthographic projection matrix.
Use 'draw_data->DisplaySize' instead of 'io.DisplaySize', and 'draw_data->DisplayPos' instead of (0,0) as the upper-left point.
You need to subtract 'draw_data->DisplayPos' from your scissor rectangles to convert them from global coordinates to frame-buffer coordinates.
- IO: Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api.
- IO: Removed io.DisplayVisibleMin, io.DisplayVisibleMax settings (they were marked obsoleted, used to clip within the (0,0)..(DisplaySize) range).
Other changes:
(FIXME: This need a fuller explanation!)
- Added ImGuiPlatformIO structure and GetPlatformIO().
Similarly to ImGuiIO and GetIO(), this structure is the main point of communication for backends supporting multi-viewports.
- Added ImGuiPlatformMonitor to feed OS monitor information in the ImGuiPlatformIO::Monitors.
- Added GetMainViewport().
- Added GetWindowViewport(), SetNextWindowViewport().
- Added GetWindowDpiScale().
- Added GetOverlayDrawList(ImGuiViewport* viewport).
The no-parameter version of GetOverlayDrawList() return the overlay for the current window's viewport.
- Added UpdatePlatformWindows(), RenderPlatformWindows(), DestroyPlatformWindows() for usage for application core.
- Added FindViewportByID(), FindViewportByPlatformHandle() for usage by backends.
- Added ImGuiConfigFlags_ViewportsEnable configuration flag and other viewport options.
- Added io.ConfigViewportsNoAutoMerge, io.ConfigViewportsNoTaskBarIcon, io.ConfigViewportsNoDecoration, io.ConfigViewportsNoDefaultParent options.
- Added ImGuiBackendFlags_PlatformHasViewports, ImGuiBackendFlags_RendererHasViewports, ImGuiBackendFlags_HasMouseHoveredViewport backend flags.
- Added io.MainViewport, io.Viewports, io.MouseHoveredViewport (MouseHoveredViewport is optional _even_ for multi-viewport support).
- Added ImGuiViewport structure, ImGuiViewportFlags flags.
- Added ImGuiWindowClass and SetNextWindowClass() for passing viewport related hints to the OS/platform back-end.
- Examples: Renderer: OpenGL2, OpenGL3, DirectX11, DirectX12, Vulkan: Added support for multi-viewports.
- Examples: Platforms: Win32, GLFW, SDL2: Added support for multi-viewports.
Note that Linux/Mac still have inconsistent support for multi-viewports. If you want to help see https://github.com/ocornut/imgui/issues/2117.
- Examples: Win32: Added DPI-related helpers to access DPI features without requiring the latest Windows SDK at compile time,
and without requiring Windows 10 at runtime.
- Examples: Vulkan: Added various optional helpers in imgui_impl_vulkan.h (they are used for multi-viewport support)
to make the examples main.cpp easier to read.
-----------------------------------------------------------------------
VERSION 1.80 (In Progress)
VERSION 1.82 WIP (In Progresss)
-----------------------------------------------------------------------
Breaking Changes:
- Added imgui_tables.cpp file! Manually constructed project files will need the new file added!
- Removed redirecting functions/enums names that were marked obsolete in 1.66 (September 2018):
- ImGui::SetScrollHere() --> use ImGui::SetScrollHereY()
- ImDrawList: upgraded AddPolyline()/PathStroke()'s "bool closed" parameter to use "ImDrawFlags flags".
- bool closed = false --> use ImDrawFlags_None, or 0
- bool closed = true --> use ImDrawFlags_Closed
The matching ImDrawFlags_Closed value is guaranteed to always stay == 1 in the future.
Difference may not be noticeable for most but zealous type-checking tools may report a need to change.
- ImDrawList: upgraded AddRect(), AddRectFilled(), PathRect() to use ImDrawFlags instead of ImDrawCornersFlags.
- ImDrawCornerFlags_TopLeft --> use ImDrawFlags_RoundCornersTopLeft
- ImDrawCornerFlags_BotRight --> use ImDrawFlags_RoundCornersBottomRight
- ImDrawCornerFlags_None --> use ImDrawFlags_RoundCornersNone etc.
Flags now sanely defaults to 0 instead of 0x0F, consistent with all other flags in the API.
IMPORTANT: The default with rounding > 0.0f is now "round all corners" vs old implicit "round no corners":
- rounding == 0.0f + flags == 0 --> meant no rounding --> unchanged (common use)
- rounding > 0.0f + flags != 0 --> meant rounding --> unchanged (common use)
- rounding == 0.0f + flags != 0 --> meant no rounding --> unchanged (unlikely use)
- rounding > 0.0f + flags == 0 --> meant no rounding --> BREAKING (unlikely use)!
- this ONLY matters for hardcoded use of 0 with rounding > 0.0f.
- fix by using named ImDrawFlags_RoundCornersNone or rounding == 0.0f!
- this is technically the only real breaking change which we can't solve automatically (it's also uncommon).
The old ImDrawCornersFlags used awkward default values of ~0 or 0xF (4 lower bits set) to signify "round all corners"
and we sometimes encouraged using them as shortcuts. As a result the legacy path still support use of hardcoded ~0
or any value from 0x1 or 0xF. They will behave the same with legacy paths enabled (will assert otherwise).
Courtesy of legacy untangling commity: [@rokups, @ocornut, @thedmd]
- ImDrawList: clarified that PathArcTo()/PathArcToFast() won't render with radius < 0.0f. Previously it sorts
of accidentally worked but would lead to counter-clockwise paths which and have an effect on anti-aliasing.
- InputText: renamed ImGuiInputTextFlags_AlwaysInsertMode to ImGuiInputTextFlags_AlwaysOverwrite, old name was an
incorrect description of behavior. Was ostly used by memory editor. Kept inline redirection function. (#2863)
- Moved 'misc/natvis/imgui.natvis' to 'misc/debuggers/imgui.natvis' as we will provide scripts for other debuggers.
- Style: renamed rarely used style.CircleSegmentMaxError (old default = 1.60f)
to style.CircleTessellationMaxError (new default = 0.30f) as its meaning changed. (#3808) [@thedmd]
- Win32+MinGW: Re-enabled IME functions by default even under MinGW. In July 2016, issue #738 had me incorrectly
disable those default functions for MinGW. MinGW users should: either link with -limm32, either set their
imconfig file with '#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS'. (#2590, #738) [@actboy168]
- Backends: Win32: Pragma linking with dwmapi.lib (Vista-era, ~9 kb). MinGW users will need to link with -ldwmapi.
Other Changes:
- Window: Shrink close button hit-testing region when it covers an abnormally high portion of the window visible
area (e.g. when window is collapsed + moved in a corner) to facilitate moving the window away. (#3825)
- Window, Nav: Fixed crash when calling SetWindowFocus(NULL) as the time a new window appears. (#3865) [@nem0]
- Nav: Various fixes for losing gamepad/keyboard navigation reference point when a window reappears or
when it appears while gamepad/keyboard are not being used. (#787)
- Drags: Fixed crash when using DragScalar() directly (not via common wrapper like DragFloat() etc.)
with ImGuiSliderFlags_AlwaysClamp + only one of either p_min or p_max set. (#3824) [@harry75369]
- Drags, Sliders: Fixed a bug where editing value would use wrong number if there were digits right after
format specifier (e.g. using "%f123" as a format string). [@rokups]
- Drags, Sliders: Fixed a bug where using custom formatting flags (',$,_) supported by stb_sprintf.h
would cause incorrect value to be displayed. (#3604) [@rokups]
- Tables: Fixed unaligned accesses when using TableSetBgColor(ImGuiTableBgTarget_CellBg). (#3872)
- IsItemHovered(): fixed return value false positive when used after EndChild(), EndGroup() or widgets using
either of them, when the hovered location is located within a child window, e.g. InputTextMultiline().
This is intended to have no side effects, but brace yourself for the possible comeback.. (#3851, #1370)
- Drag and Drop: can use BeginDragDropSource() for other than the left mouse button as long as the item
has an ID (for ID-less items will add new functionalities later). (#1637, #3885)
- Added GetAllocatorFunctions() to facilitate sharing allocators accross DLL boundaries. (#3836)
- ImFontAtlas: Added 'bool TexPixelsUseColors' output to help backend decide of underlying texture format. (#3369)
This can currently only ever be set by the Freetype renderer.
- imgui_freetype: Added ImGuiFreeTypeBuilderFlags_Bitmap flag to request Freetype loading bitmap data.
This may have an effect on size and must be called with correct size values. (#3879) [@metarutaiga]
- ImDrawList: PathArcTo() now supports "int num_segments = 0" (new default) and adaptively tesselate.
The adapative tesselation uses look up tables, tends to be faster than old PathArcTo() while maintaining
quality for large arcs (tesselation quality derived from "style.CircleTessellationMaxError") (#3491) [@thedmd]
- ImDrawList: PathArcToFast() also adaptively tesselate efficiently. This means that large rounded corners
in e.g. hi-dpi settings will generally look better. (#3491) [@thedmd]
- ImDrawList: AddCircle, AddCircleFilled(): Tweaked default segment count calculation to honor MaxError
with more accuracy. Made default segment count always even for better looking result. (#3808) [@thedmd]
- Misc: Added 'debuggers/imgui.gdb' and 'debuggers/imgui.natstepfilter' (along with existing 'imgui.natvis')
scriptss to configure popular debuggers into skipping trivial functions when using StepInto. [@rokups]
- Backends: Android: Added native Android backend. (#3446) [@duddel]
- Backends: Win32: Added ImGui_ImplWin32_EnableAlphaCompositing() to facilitate experimenting with
alpha compositing and transparent windows. (#2766, #3447 etc.).
- Backends: OpenGL, Vulkan, DX9, DX10, DX11, DX12, Metal, WebGPU, Allegro: Rework blending equation to
preserve alpha in output buffer (using SrcBlendAlpha = ONE, DstBlendAlpha = ONE_MINUS_SRC_ALPHA consistently
accross all backends), facilitating compositing of the output buffer with another buffer.
(#2693, #2764, #2766, #2873, #3447, #3813, #3816) [@ocornut, @thedmd, @ShawnM427, @Ubpa, @aiekick]
- Backends: DX9: Fix to support IMGUI_USE_BGRA_PACKED_COLOR. (#3844) [@Xiliusha]
- Backends: DX9: Fix to support colored glyphs, using newly introduced 'TexPixelsUseColors' info. (#3844)
- Examples: Android: Added Android + GL ES2 example. (#3446) [@duddel]
- Examples: Reworked setup of clear color to be compatible with transparent values.
- CI: Use a dedicated "scheduled" workflow to trigger scheduled builds. Forks may disable this workflow if
scheduled builds builds are not required. [@rokups]
- Log/Capture: Added LogTextV, a va_list variant of LogText. [@PathogenDavid]
-----------------------------------------------------------------------
VERSION 1.81 (Released 2021-02-10)
-----------------------------------------------------------------------
Breaking Changes:
- ListBox helpers:
- Renamed ListBoxHeader(const char* label, ImVec2 size) to BeginListBox().
- Renamed ListBoxFooter() to EndListBox().
- Removed ListBoxHeader(const char* label, int items_count, int height_in_items = -1) in favor of specifying size.
In the redirection function, made vertical padding consistent regardless of (items_count <= height_in_items) or not.
- Kept inline redirection function for all threes (will obsolete).
- imgui_freetype:
- Removed ImGuiFreeType::BuildFontAtlas(). Kept inline redirection function.
Prefer using '#define IMGUI_ENABLE_FREETYPE', but there's a runtime selection path available too.
- The shared extra flags parameters (very rarely used) are now stored in ImFontAtlas::FontBuilderFlags.
- Renamed ImFontConfig::RasterizerFlags (used by FreeType) to ImFontConfig::FontBuilderFlags.
- Renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API.
Other Changes:
- Viewports Added ImGui::GetMainViewport() as a way to get the bounds and work area of the host display. (#3789, #1542)
- In 'master' branch or without multi-viewports feature enabled:
- GetMainViewport()->Pos is always == (0,0)
- GetMainViewport()->Size is always == io.DisplaySize
- In 'docking' branch and with the multi-viewports feature enabled:
- GetMainViewport() will return information from your host Platform Window.
- In the future, we will support a "no main viewport" mode and this may return bounds of your main monitor.
- For forward compatibility with multi-viewports/multi-monitors:
- Code using (0,0) as a way to signify "upper-left of the host window" should use GetMainViewport()->Pos.
- Code using io.DisplaySize as a way to signify "size of the host window" should use GetMainViewport()->Size.
- We are also exposing a work area in ImGuiViewport ('WorkPos', 'WorkSize' vs 'Pos', 'Size' for full area):
- For a Platform Window, the work area is generally the full area minus space used by menu-bars.
- For a Platform Monitor, the work area is generally the full area minus space used by task-bars.
- All of this has been the case in 'docking' branch for a long time. What we've done is merely merging
a small chunk of the multi-viewport logic into 'master' to standardize some concepts ahead of time.
- Tables: Fixed PopItemWidth() or multi-components items not restoring per-colum ItemWidth correctly. (#3760)
- Window: Fixed minor title bar text clipping issue when FramePadding is small/zero and there are no
close button in the window. (#3731)
- SliderInt: Fixed click/drag when v_min==v_max from setting the value to zero. (#3774) [@erwincoumans]
Would also repro with DragFloat() when using ImGuiSliderFlags_Logarithmic with v_min==v_max.
- Menus: Fixed an issue with child-menu auto sizing (issue introduced in 1.80 on 2021/01/25) (#3779)
- InputText: Fixed slightly off ScrollX tracking, noticeable with large values of FramePadding.x. (#3781)
- InputText: Multiline: Fixed padding/cliprect not precisely matching single-line version. (#3781)
- InputText: Multiline: Fixed FramePadding.y worth of vertical offset when aiming with mouse.
- ListBox: Tweaked default height calculation.
- Fonts: imgui_freetype: Facilitated using FreeType integration: [@Xipiryon, @ocornut]
- Use '#define IMGUI_ENABLE_FREETYPE' in imconfig.h should make it work with no other modifications
other than compiling misc/freetype/imgui_freetype.cpp and linking with FreeType.
- Use '#define IMGUI_ENABLE_STB_TRUETYPE' if you somehow need the stb_truetype rasterizer to be
compiled in along with the FreeType one, otherwise it is enabled by default.
- Fonts: imgui_freetype: Added support for colored glyphs as supported by Freetype 2.10+ (for .ttf using CPAL/COLR
tables only). Enable the ImGuiFreeTypeBuilderFlags_LoadColor on a given font. Atlas always output directly
as RGBA8 in this situation. Likely to make sense with IMGUI_USE_WCHAR32. (#3369) [@pshurgal]
- Fonts: Fixed CalcTextSize() width rounding so it behaves more like a ceil. This is in order for text wrapping
to have enough space when provided width precisely calculated with CalcTextSize().x. (#3776)
Note that the rounding of either positions and widths are technically undesirable (e.g. #3437, #791) but
variety of code is currently on it so we are first fixing current behavior before we'll eventually change it.
- Log/Capture: Fix various new line/spacing issue when logging widgets. [@Xipiryon, @ocornut]
- Log/Capture: Improved the ASCII look of various widgets, making large dumps more easily human readable.
- ImDrawList: Fixed AddCircle()/AddCircleFilled() with (rad > 0.0f && rad < 1.0f && num_segments == 0). (#3738)
Would lead to a buffer read overflow.
- ImDrawList: Clarified PathArcTo() need for a_min <= a_max with an assert.
- ImDrawList: Fixed PathArcToFast() handling of a_min > a_max.
- Metrics: Back-ported "Viewports" debug visualizer from 'docking' branch.
- Demo: Added 'Examples->Fullscreen Window' demo using GetMainViewport() values. (#3789)
- Demo: 'Simple Overlay' demo now moves under main menu-bar (if any) using GetMainViewport()'s work area.
- Backends: Win32: Dynamically loading XInput DLL instead of linking with it, facilitate compiling with
old WindowSDK versions or running on Windows 7. (#3646, #3645, #3248, #2716) [@Demonese]
- Backends: Vulkan: Add support for custom Vulkan function loader and VK_NO_PROTOTYPES. (#3759, #3227) [@Hossein-Noroozpour]
User needs to call ImGui_ImplVulkan_LoadFunctions() with their custom loader prior to other functions.
- Backends: Metal: Fixed texture storage mode when building on Mac Catalyst. (#3748) [@Belinsky-L-V]
- Backends: OSX: Fixed mouse position not being reported when mouse buttons other than left one are down. (#3762) [@rokups]
- Backends: WebGPU: Added enderer backend for WebGPU support (imgui_impl_wgpu.cpp) (#3632) [@bfierz]
Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.
- Examples: WebGPU: Added Emscripten+WebGPU example. (#3632) [@bfierz]
- Backends: GLFW: Added ImGui_ImplGlfw_InitForOther() initialization call to use with non OpenGL API. (#3632)
-----------------------------------------------------------------------
VERSION 1.80 (Released 2021-01-21)
-----------------------------------------------------------------------
Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.80
Breaking Changes:
- Added imgui_tables.cpp file! Manually constructed project files will need the new file added! (#3740)
- Backends: moved all backends files (imgui_impl_XXXX.cpp, imgui_impl_XXXX.h) from examples/ to backends/. (#3513)
- Removed redirecting functions/enums names that were marked obsolete in 1.60 (April 2017):
- Renamed ImDrawList::AddBezierCurve() to ImDrawList::AddBezierCubic(). Kept inline redirection function (will obsolete).
- Renamed ImDrawList::PathBezierCurveTo() to ImDrawList::PathBezierCubicCurveTo(). Kept inline redirection function (will obsolete).
- Removed redirecting functions/enums names that were marked obsolete in 1.60 (April 2018):
- io.RenderDrawListsFn pointer -> use ImGui::GetDrawData() value and call the render function of your backend
- ImGui::IsAnyWindowFocused() -> use ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow)
- ImGui::IsAnyWindowHovered() -> use ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow)
@ -117,45 +222,64 @@ Breaking Changes:
- Removed redirecting functions/enums names that were marked obsolete in 1.61 (May 2018):
- InputFloat (... int decimal_precision ...) -> use InputFloat (... const char* format ...) with format = "%.Xf" where X was value for decimal_precision.
- same for InputFloat2()/InputFloat3()/InputFloat4() variants taking a `int decimal_precision` parameter.
- Removed redirecting functions/enums names that were marked obsolete in 1.63 (August 2018):
- ImGui::IsItemDeactivatedAfterChange() -> use ImGui::IsItemDeactivatedAfterEdit().
- ImGuiCol_ModalWindowDarkening -> use ImGuiCol_ModalWindowDimBg
- ImGuiInputTextCallback -> use ImGuiTextEditCallback
- ImGuiInputTextCallbackData -> use ImGuiTextEditCallbackData
- If you were still using the old names, while you are cleaning up, considering enabling
IMGUI_DISABLE_OBSOLETE_FUNCTIONS in imconfig.h even temporarily to have a pass at finding
and removing up old API calls, if any remaining.
- Columns: renamed undocumented/internals ImGuiColumnsFlags_* to ImGuiOldColumnFlags_* in prevision of
incoming Tables API. Keep redirection enums (will obsolete). (#125, #513, #913, #1204, #1444, #2142, #2707)
- Renamed io.ConfigWindowsMemoryCompactTimer to io.ConfigMemoryCompactTimer as the feature will apply
- Internals: Columns: renamed undocumented/internals ImGuiColumnsFlags_* to ImGuiOldColumnFlags_* to reduce
confusion with Tables API. Keep redirection enums (will obsolete). (#125, #513, #913, #1204, #1444, #2142, #2707)
- Renamed io.ConfigWindowsMemoryCompactTimer to io.ConfigMemoryCompactTimer as the feature now applies
to other data structures. (#2636)
Other Changes:
- Tables: added new Tables Beta API as a replacement for old Columns. (#2957, #125)
Check out 'Demo->Tables' for many demos + API comments in imgui.h for details.
- Added 16 functions: BeginTable(), EndTable(),
TableNextRow(), TableNextColumn(), TableSetColumnIndex(), TableGetColumnIndex(), TableGetRowIndex(),
TableSetupColumn(), TableSetupScrollFreeze(),
TableHeadersRow(), TableHeader(), TableSetBgColor(), TableGetSortSpecs(),
TableGetColumnCount(), TableGetColumnName(), TableGetColumnFlags().
- Added 2 structures: ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs.
- Added 2 enums: ImGuiSortDirection, ImGuiTableBgTarget.
- Added 3 flags sets: ImGuiTableFlags (27 flags), ImGuiTableColumnFlags (24 flags), ImGuiTableRowFlags (1 flags).
- Added 5 colors: ImGuiCol_TableHeaderBg, ImGuiCol_TableBorderStrong, ImGuiCol_TableBorderLight, ImGuiCol_TableRowBg, ImGuiCol_TableRowBgAlt.
- Added 1 style var: ImGuiStyleVar_CellPadding.
- Tables: added new Tables Beta API as a replacement for old Columns. (#3740, #2957, #125)
Check out 'Demo->Tables' for many demos.
Read API comments in imgui.h for details. Read extra commentary in imgui_tables.cpp.
- Added 16 functions:
- BeginTable(), EndTable()
- TableNextRow(), TableNextColumn(), TableSetColumnIndex()
- TableSetupColumn(), TableSetupScrollFreeze()
- TableHeadersRow(), TableHeader()
- TableGetRowIndex(), TableGetColumnCount(), TableGetColumnIndex(), TableGetColumnName(), TableGetColumnFlags()
- TableGetSortSpecs(), TableSetBgColor()
- Added 3 flags sets:
- ImGuiTableFlags (29 flags for: features, decorations, sizing policies, padding, clipping, scrolling, sorting etc.)
- ImGuiTableColumnFlags (24 flags for: width policies, default settings, sorting options, indentation options etc.)
- ImGuiTableRowFlags (1 flag for: header row)
- Added 2 structures: ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs
- Added 2 enums: ImGuiSortDirection, ImGuiTableBgTarget
- Added 1 style variable: ImGuiStyleVar_CellPadding
- Added 5 style colors: ImGuiCol_TableHeaderBg, ImGuiCol_TableBorderStrong, ImGuiCol_TableBorderLight, ImGuiCol_TableRowBg, ImGuiCol_TableRowBgAlt.
- Tab Bar: Made it possible to append to an existing tab bar by calling BeginTabBar()/EndTabBar() again.
- Tab Bar: Fixed using more than 128 tabs in a tab bar (scrolling policy recommended).
- Tab Bar: Do not display a tooltip if the name already fits over a given tab. (#3521)
- Tab Bar: Fixed minor/unlikely bug skipping over a button when scrolling left with arrows.
- Tab Bar: Requested ideal content size (for auto-fit) doesn't affect horizontal scrolling. (#3414)
- Drag and Drop: Fix losing drop source ActiveID (and often source tooltip) when opening a TreeNode()
or CollapsingHeader() while dragging. (#1738)
- Drag and Drop: Fix drag and drop to tie same-size drop targets by choosen the later one. Fixes dragging
- Drag and Drop: Fix drag and drop to tie same-size drop targets by chosen the later one. Fixes dragging
into a full-window-sized dockspace inside a zero-padded window. (#3519, #2717) [@Black-Cat]
- Checkbox: Added CheckboxFlags() helper with int* type.
- Checkbox: Added CheckboxFlags() helper with int* type (internals have a template version, not exposed).
- Clipper: Fixed incorrect end-list positioning when using ImGuiListClipper with 1 item (bug in 1.79). (#3663) [@nyorain]
- InputText: Fixed updating cursor/selection position when a callback altered the buffer in a way
where the byte count is unchanged but the decoded character count changes. (#3587) [@gqw]
- InputText: Fixed swiching from single to multi-line while preserving same ID.
- InputText: Fixed switching from single to multi-line while preserving same ID.
- Combo: Fixed using IsItemEdited() after Combo() not matching the return value from Combo(). (#2034)
- DragFloat, DragInt: very slightly increased mouse drag threshold + expressing it as a factor of default value.
- DragFloat, DragInt: added experimental io.ConfigDragClickToInputText feature to enable turning DragXXX widgets
into text input with a simple mouse click-release (without moving). (#3737)
- Nav: Fixed IsItemFocused() from returning false when Nav highlight is hidden because mouse has moved.
It's essentially been always the case but it doesn't make much sense. Instead we will aim at exposing
feedback and control of keyboard/gamepad navigation highlight and mouse hover disable flag. (#787, #2048)
- Metrics: Fixed mishandling of ImDrawCmd::VtxOffset in wireframe mesh renderer.
- Metrics: Rebranded as "Dear ImGui Metrics/Debugger" to clarify its purpose.
- ImDrawList: Added ImDrawList::AddQuadBezierCurve(), ImDrawList::PathQuadBezierCurveTo() quadratic bezier
helpers. (#3127, #3664, #3665) [@aiekick]
- Fonts: Updated GetGlyphRangesJapanese() to include a larger 2999 ideograms selection of Joyo/Jinmeiyo
kanjis, from the previous 1946 ideograms selection. This will consume a some more memory but be generally
much more fitting for Japanese display, until we switch to a more dynamic atlas. (#3627) [@vaiorabbit]
@ -170,25 +294,37 @@ Other Changes:
- Misc: Made EndFrame() assertion for key modifiers being unchanged during the frame (added in 1.76) more
lenient, allowing full mid-frame releases. This is to accommodate the use of mid-frame modal native
windows calls, which leads backends such as GLFW to send key clearing events on focus loss. (#3575)
- Style: Changed default style.WindowRounding value to 0.0f (matches default for multi-viewports).
- Style: Reduced the size of the resizing grip, made alpha less prominent.
- Style: Classic: Increase the default alpha value of WindowBg to be closer to other styles.
- Demo: Clarify usage of right-aligned items in Demo>Layout>Widgets Width.
- Backends: OpenGL3: Use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...)
when the later returns zero (e.g. Desktop GL 2.x). (#3530) [@xndcn]
- Backends: OpenGL2: Backup and restore GL_SHADE_MODEL and disable GL_NORMAL_ARRAY state to increase
compatibility with legacy code. (#3671)
- Backends: OpenGL3: Backup and restore GL_PRIMITIVE_RESTART state. (#3544) [@Xipiryon]
- Backends: Vulkan: Added support for specifying which subpass to reference during VkPipeline creation. (@3579) [@bdero]
- Backends: OpenGL2, OpenGL3: Backup and restore GL_STENCIL_TEST enable state. (#3668)
- Backends: Vulkan: Added support for specifying which sub-pass to reference during VkPipeline creation. (@3579) [@bdero]
- Backends: DX12: Improve Windows 7 compatibility (for D3D12On7) by loading d3d12.dll dynamically. (#3696) [@Mattiwatti]
- Backends: Win32: Fix setting of io.DisplaySize to invalid/uninitialized data after hwnd has been closed.
- Backends: OSX: Fix keypad-enter key not working on MacOS. (#3554) [@rokups, @lfnoise]
- Examples: Apple+Metal: Consolidated/simplified to get closer to other examples. (#3543) [@warrenm]
- Examples: Apple+Metal: Forward events down so OS key combination like Cmd+Q can work. (#3554) [@rokups]
- Examples: Emscripten: Renamed example_emscripten/ to example_emscripten_opengl3/. (#3632)
- Examples: Emscripten: Added 'make serve' helper to spawn a web-server on localhost. (#3705) [@Horki]
- Examples: DirectX12: Move ImGui::Render() call above the first barrier to clarify its lack of effect on the graphics pipe.
- CI: Fix testing for Windows DLL builds. (#3603, #3601) [@iboB]
- Docs: Split examples/README.txt into docs/BACKENDS.md and docs/EXAMPLES.md improved them.
- Docs: Consistently renamed all occurences of "binding" and "back-end" to "backend" in comments and docs.
- Docs: Improved the wiki and added a https://github.com/ocornut/imgui/wiki/Useful-Widgets page. [@Xipiryon]
- Docs: Split examples/README.txt into docs/BACKENDS.md and docs/EXAMPLES.md, and improved them.
- Docs: Consistently renamed all occurrences of "binding" and "back-end" to "backend" in comments and docs.
-----------------------------------------------------------------------
VERSION 1.79 (Released 2020-10-08)
-----------------------------------------------------------------------
Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.79
Breaking Changes:
- Fonts: Removed ImFont::DisplayOffset in favor of ImFontConfig::GlyphOffset. DisplayOffset was applied
@ -228,7 +364,7 @@ Other Changes:
- InputText: Fixed callback's helper DeleteChars() function when cursor is inside the deleted block. (#3454)
- InputText: Made pressing Down arrow on the last line when it doesn't have a carriage return not move to
the end of the line (so it is consistent with Up arrow, and behave same as Notepad and Visual Studio.
Note that some other text editors instead would move the crusor to the end of the line). [@Xipiryon]
Note that some other text editors instead would move the cursor to the end of the line). [@Xipiryon]
- DragFloat, DragScalar: Fixed ImGuiSliderFlags_ClampOnInput not being honored in the special case
where v_min == v_max. (#3361)
- SliderInt, SliderScalar: Fixed reaching of maximum value with inverted integer min/max ranges, both
@ -256,7 +392,7 @@ Other Changes:
tabs reordered in the tab list popup. [@Xipiryon]
- Columns: Fix inverted ClipRect being passed to renderer when using certain primitives inside of
a fully clipped column. (#3475) [@szreder]
- Popups, Tooltips: Fix edge cases issues with positionning popups and tooltips when they are larger than
- Popups, Tooltips: Fix edge cases issues with positioning popups and tooltips when they are larger than
viewport on either or both axises. [@Rokups]
- Fonts: AddFontDefault() adjust its vertical offset based on floor(size/13) instead of always +1.
Was previously done by altering DisplayOffset.y but wouldn't work for DPI scaled font.
@ -281,6 +417,8 @@ Other Changes:
VERSION 1.78 (Released 2020-08-18)
-----------------------------------------------------------------------
Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.78
Breaking Changes:
- Obsoleted use of the trailing 'float power=1.0f' parameter for those functions: [@Shironekoben, @ocornut]
@ -418,7 +556,7 @@ Other Changes:
- Popups: Added ImGuiPopupFlags_AnyPopupId and ImGuiPopupFlags_AnyPopupLevel flags for IsPopupOpen(),
allowing to check if any popup is open at the current level, if a given popup is open at any popup
level, if any popup is open at all.
- Popups: Fix an edge case where programatically closing a popup while clicking on its empty space
- Popups: Fix an edge case where programmatically closing a popup while clicking on its empty space
would attempt to focus it and close other popups. (#2880)
- Popups: Fix BeginPopupContextVoid() when clicking over the area made unavailable by a modal. (#1636)
- Popups: Clarified some of the comments and function prototypes.
@ -1218,7 +1356,6 @@ Breaking Changes:
- Renamed ImFontAtlas::GlyphRangesBuilder to ImFontGlyphRangesBuilder. Kept redirection typedef (will obsolete).
Other Changes:
- Added BETA api for Tab Bar/Tabs widgets: (#261, #351)
- Added BeginTabBar(), EndTabBar(), BeginTabItem(), EndTabItem(), SetTabItemClosed() API.
- Added ImGuiTabBarFlags flags for BeginTabBar().
@ -1556,7 +1693,7 @@ Other Changes:
- ImFontAtlas: Added GetGlyphRangesChineseSimplifiedCommon() helper that returns a list of ~2500 most common Simplified Chinese
characters. (#1859) [@JX-Master, @ocornut]
- Examples: OSX: Added imgui_impl_osx.mm backend to be used along with e.g. imgui_impl_opengl2.cpp. (#281, #1870) [@pagghiu, @itamago, @ocornut]
- Examples: GLFW: Made it possible to Shutdown/Init the backend again (by reseting the time storage properly). (#1827) [@ice1000]
- Examples: GLFW: Made it possible to Shutdown/Init the backend again (by resetting the time storage properly). (#1827) [@ice1000]
- Examples: Win32: Fixed handling of mouse wheel messages to support sub-unit scrolling messages (typically sent by track-pads). (#1874) [@zx64]
- Examples: SDL+Vulkan: Added SDL+Vulkan example.
- Examples: Allegro5: Added support for ImGuiConfigFlags_NoMouseCursorChange flag. Added clipboard support.
@ -2331,7 +2468,7 @@ Other Changes:
- Combo(): Right-most button stays highlighted when pop-up is open.
- Combo(): Display pop-up above if there's isn't enough space below / or select largest side. (#505)
- DragFloat(), SliderFloat(), InputFloat(): fixed cases of erroneously returning true repeatedly after a text input modification (e.g. "0.0" --> "0.000" would keep returning true). (#564)
- DragFloat(): Always apply value when mouse is held/widget active, so that an always-reseting variable (e.g. non saved local) can be passed.
- DragFloat(): Always apply value when mouse is held/widget active, so that an always-resetting variable (e.g. non saved local) can be passed.
- InputText(): OS X friendly behaviors: Word movement uses ALT key; Shortcuts uses CMD key; Double-clicking text select a single word; Jumping to next word sets cursor to end of current word instead of beginning of current word. (@zhiayang), (#473)
- InputText(): Added BufTextLen in ImGuiTextEditCallbackData. Requesting user to maintain it if buffer is modified. Zero-ing structure properly before use. (#541)
- CheckboxFlags(): Added support for testing/setting multiple flags at the same time. (@DMartinek) (#555)

View File

@ -79,6 +79,10 @@ Changelog, so if you want to update them later it will be easier to catch up wit
Allegro 5 example. <BR>
= main.cpp + imgui_impl_allegro5.cpp
[example_android_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_android_opengl3/) <BR>
Android + OpenGL3 (ES) example. <BR>
= main.cpp + imgui_impl_android.cpp + imgui_impl_opengl3.cpp
[example_apple_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_metal/) <BR>
OSX & iOS + Metal example. <BR>
= main.m + imgui_impl_osx.mm + imgui_impl_metal.mm <BR>
@ -98,6 +102,10 @@ Emcripten + SDL2 + OpenGL3+/ES2/ES3 example. <BR>
Note that other examples based on SDL or GLFW + OpenGL could easily be modified to work with Emscripten.
We provide this to make the Emscripten differences obvious, and have them not pollute all other examples.
[example_emscripten_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_emscripten_wgpu/) <BR>
Emcripten + GLFW + WebGPU example. <BR>
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_wgpu.cpp
[example_glfw_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_metal/) <BR>
GLFW (Mac) + Metal example. <BR>
= main.mm + imgui_impl_glfw.cpp + imgui_impl_metal.mm
@ -198,9 +206,9 @@ This is quite long and tedious, because: DirectX12.
**Building**
Unfortunately in 2020 it is still tedious to create and maintain portable build files using external
Unfortunately nowadays it is still tedious to create and maintain portable build files using external
libraries (the kind we're using here to create a window and render 3D triangles) without relying on
third party software. For most examples here we choose to provide:
third party software and build systems. For most examples here we choose to provide:
- Makefiles for Linux/OSX
- Batch files for Visual Studio 2008+
- A .sln project file for Visual Studio 2012+

View File

@ -23,7 +23,7 @@ or view this file with any Markdown viewer.
| [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) |
| [I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries..](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-displaying-outside-their-expected-windows-boundaries) |
| **Q&A: Usage** |
| **[Why is my widget not reacting when I click on it?<br>How can I have multiple widgets with the same label?<br>Why are multiple widgets reacting when I interact with one?](#q-why-is-my-widget-not-reacting-when-i-click-on-it)** |
| **[Why is my widget not reacting when I click on it?<br>How can I have widgets with an empty label?<br>How can I have multiple widgets with the same label?](#q-why-is-my-widget-not-reacting-when-i-click-on-it)** |
| [How can I display an image? What is ImTextureID, how does it work?](#q-how-can-i-display-an-image-what-is-imtextureid-how-does-it-work)|
| [How can I use my own math types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-math-types-instead-of-imvec2imvec4) |
| [How can I interact with standard C++ types (such as std::string and std::vector)?](#q-how-can-i-interact-with-standard-c-types-such-as-stdstring-and-stdvector) |
@ -48,13 +48,13 @@ or view this file with any Markdown viewer.
### Q: Where is the documentation?
**This library is poorly documented at the moment and expects of the user to be acquainted with C/C++.**
- The [Wiki](https://github.com/ocornut/imgui/wiki) is a hub to many resources and links.
- Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder to explain how to integrate Dear ImGui with your own engine/application. You can run those applications and explore them.
- See demo code in [imgui_demo.cpp](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp) and particularly the `ImGui::ShowDemoWindow()` function. The demo covers most features of Dear ImGui, so you can read the code and see its output.
- See documentation: [Backends](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md), [Examples](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md), [Fonts](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md).
- See documentation and comments at the top of [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp) + general API comments in [imgui.h](https://github.com/ocornut/imgui/blob/master/imgui.h).
- The [Wiki](https://github.com/ocornut/imgui/wiki) has many resources and links.
- The [Glossary](https://github.com/ocornut/imgui/wiki/Glossary) page may be useful.
- The [Issues](https://github.com/ocornut/imgui/issues) section can be searched for past questions and issues.
- The [Issues](https://github.com/ocornut/imgui/issues) and [Discussions](https://github.com/ocornut/imgui/discussions) sections can be searched for past questions and issues.
- Your programming IDE is your friend, find the type or function declaration to find comments associated to it.
- The `ImGui::ShowMetricsWindow()` function exposes lots of internal information and tools. Although it is primary designed as a debugging tool, having access to that information tends to help understands concepts.
@ -94,7 +94,8 @@ You may merge in the [tables](https://github.com/ocornut/imgui/tree/tables) bran
Read [EXAMPLES.md](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md). <BR>
Read [BACKENDS.md](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md). <BR>
Read `PROGRAMMER GUIDE` section of [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp).
Read `PROGRAMMER GUIDE` section of [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp). <BR>
The [Wiki](https://github.com/ocornut/imgui/wiki) is a hub to many resources and links.
##### [Return to Index](#index)
@ -103,15 +104,25 @@ Read `PROGRAMMER GUIDE` section of [imgui.cpp](https://github.com/ocornut/imgui/
### Q: How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application?
You can read the `io.WantCaptureMouse`, `io.WantCaptureKeyboard` and `io.WantTextInput` flags from the ImGuiIO structure.
- When `io.WantCaptureMouse` is set, you need to discard/hide the mouse inputs from your underlying application.
- When `io.WantCaptureKeyboard` is set, you need to discard/hide the keyboard inputs from your underlying application.
- When `io.WantTextInput` is set, you can notify your OS/engine to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console OS).
e.g. `if (ImGui::GetIO().WantCaptureMouse) { ... }`
Important: you should always pass your mouse/keyboard inputs to Dear ImGui, regardless of the value `io.WantCaptureMouse`/`io.WantCaptureKeyboard`. This is because e.g. we need to detect that you clicked in the void to unfocus its own windows, and other reasons.
- When `io.WantCaptureMouse` is set, imgui wants to use your mouse state, and you may want to discard/hide the inputs from the rest of your application.
- When `io.WantCaptureKeyboard` is set, imgui wants to use your keyboard state, and you may want to discard/hide the inputs from the rest of your application.
- When `io.WantTextInput` is set to may want to notify your OS to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console OS).
```cpp
void MyLowLevelMouseButtonHandler(int button, bool down)
{
// (1) ALWAYS forward mouse data to ImGui! This is automatic with default backends. With your own backend:
ImGuiIO& io = ImGui::GetIO();
io.MouseDown[button] = down;
// (2) ONLY forward mouse data to your underlying app/game.
if (!io.WantCaptureMouse)
my_game->HandleMouseData(...);
}
```
**Note:** You should always pass your mouse/keyboard inputs to Dear ImGui, even when the io.WantCaptureXXX flag are set false.
This is because imgui needs to detect that you clicked in the void to unfocus its own windows.
**Note:** The `io.WantCaptureMouse` is more correct that any manual attempt to "check if the mouse is hovering a window" (don't do that!). It handle mouse dragging correctly (both dragging that started over your application or over a Dear ImGui window) and handle e.g. popup and modal windows blocking inputs.
@ -214,8 +225,6 @@ Button("OK"); // Label = "OK", ID = hash of ("MyOtherWindow", "OK")
End();
```
We used "..." above to signify whatever was already pushed to the ID stack previously:
- If you have a same ID twice in the same location, you'll have a conflict:
```cpp
Button("OK");
@ -429,10 +438,8 @@ provide similar or better string helpers.
### Q: How can I display custom shapes? (using low-level ImDrawList API)
- You can use the low-level `ImDrawList` api to render shapes within a window.
```cpp
if (!ImGui::Begin("My shapes"))
return;
ImGui::Begin("My shapes");
ImDrawList* draw_list = ImGui::GetWindowDrawList();
@ -456,8 +463,9 @@ ImGui::End();
- To generate colors: you can use the macro `IM_COL32(255,255,255,255)` to generate them at compile time, or use `ImGui::GetColorU32(IM_COL32(255,255,255,255))` or `ImGui::GetColorU32(ImVec4(1.0f,1.0f,1.0f,1.0f))` to generate a color that is multiplied by the current value of `style.Alpha`.
- Math operators: if you have setup `IM_VEC2_CLASS_EXTRA` in `imconfig.h` to bind your own math types, you can use your own math types and their natural operators instead of ImVec2. ImVec2 by default doesn't export any math operators in the public API. You may use `#define IMGUI_DEFINE_MATH_OPERATORS` `#include "imgui_internal.h"` to use the internally defined math operators, but instead prefer using your own math library and set it up in `imconfig.h`.
- You can use `ImGui::GetBackgroundDrawList()` or `ImGui::GetForegroundDrawList()` to access draw lists which will be displayed behind and over every other dear imgui windows (one bg/fg drawlist per viewport). This is very convenient if you need to quickly display something on the screen that is not associated to a dear imgui window.
- You can also create your own empty window and draw inside it. Call Begin() with the NoBackground | NoDecoration | NoSavedSettings | NoInputs flags (The `ImGuiWindowFlags_NoDecoration` flag itself is a shortcut for NoTitleBar | NoResize | NoScrollbar | NoCollapse). Then you can retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like.
- You can create your own ImDrawList instance. You'll need to initialize them with `ImGui::GetDrawListSharedData()`, or create your own instancing ImDrawListSharedData, and then call your renderer function with your own ImDrawList or ImDrawData data.
- You can also create your own empty window and draw inside it. Call Begin() with the NoBackground | NoDecoration | NoSavedSettings | NoInputs flags (The `ImGuiWindowFlags_NoDecoration` flag itself is a shortcut for NoTitleBar | NoResize | NoScrollbar | NoCollapse). Then you can retrieve the ImDrawList* via `GetWindowDrawList()` and draw to it in any way you like.
`- You can create your own ImDrawList instance. You'll need to initialize them with `ImGui::GetDrawListSharedData()`, or create your own instancing ImDrawListSharedData`, and then call your renderer function with your own ImDrawList or ImDrawData data.
- Looking for fun? The [ImDrawList coding party 2020](https://github.com/ocornut/imgui/issues/3606) thread is full of "don't do this at home" extreme uses of the ImDrawList API.
##### [Return to Index](#index)
@ -603,6 +611,7 @@ You may take a look at:
- [Quotes](https://github.com/ocornut/imgui/wiki/Quotes)
- [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui)
- [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors)
- [Gallery](https://github.com/ocornut/imgui/issues/3488)
##### [Return to Index](#index)
@ -647,7 +656,7 @@ There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/ci
### Q: How can I help?
- Businesses: please reach out to `contact AT dearimgui.com` if you work in a place using Dear ImGui! We can discuss ways for your company to fund development via invoiced technical support, maintenance or sponsoring contacts. This is among the most useful thing you can do for Dear ImGui. With increased funding we can hire more people working on this project.
- Individuals: you can support continued maintenance and development via PayPal donations. See [README](https://github.com/ocornut/imgui/blob/master/docs/README.md).
- If you are experienced with Dear ImGui and C++, look at the [GitHub Issues](https://github.com/ocornut/imgui/issues), look at the [Wiki](https://github.com/ocornut/imgui/wiki), read [docs/TODO.txt](https://github.com/ocornut/imgui/blob/master/docs/TODO.txt) and see how you want to help and can help!
- If you are experienced with Dear ImGui and C++, look at [GitHub Issues](https://github.com/ocornut/imgui/issues), [GitHub Discussions](https://github.com/ocornut/imgui/discussions), the [Wiki](https://github.com/ocornut/imgui/wiki), read [docs/TODO.txt](https://github.com/ocornut/imgui/blob/master/docs/TODO.txt) and see how you want to help and can help!
- Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere etc.
You may post screenshot or links in the [gallery threads](https://github.com/ocornut/imgui/issues/3488). Visuals are ideal as they inspire other programmers. Disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions.
- If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues or sometimes incomplete PR.

View File

@ -8,9 +8,7 @@ a 13 pixels high, pixel-perfect font used by default. We embed it in the source
You may also load external .TTF/.OTF files.
In the [misc/fonts/](https://github.com/ocornut/imgui/tree/master/misc/fonts) folder you can find a few suggested fonts, provided as a convenience.
**Read the FAQ:** https://www.dearimgui.org/faq (there is a Fonts section!)
**Use the Discord server**: http://discord.dearimgui.org and not the GitHub issue tracker for basic font loading questions.
**Also read the FAQ:** https://www.dearimgui.org/faq (there is a Fonts section!)
## Index
- [Readme First](#readme-first)
@ -70,11 +68,13 @@ If you get an assert stating "Could not load font file!", your font filename is
**Load multiple fonts:**
```cpp
// Init
ImGuiIO& io = ImGui::GetIO();
ImFont* font1 = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels);
ImFont* font2 = io.Fonts->AddFontFromFileTTF("anotherfont.otf", size_pixels);
// Select font at runtime
```
```cpp
// In application loop: select font at runtime
ImGui::Text("Hello"); // use the default font (which is the first loaded font)
ImGui::PushFont(font2);
ImGui::Text("Hello with another font");
@ -145,19 +145,18 @@ ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
**Font Atlas too large?**
- If you have very 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 glyphs appears as white rectangles.
- In particular, using a large range such as `GetGlyphRangesChineseSimplifiedCommon()` is not recommended unless you set `OversampleH`/`OversampleV` to 1 and use a small font size.
- 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.
- 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:
1. Reduce glyphs ranges by calculating them from source localization data.
You can use the `ImFontGlyphRangesBuilder` for this purpose, this will be the biggest win!
2. You may reduce oversampling, e.g. `font_config.OversampleH = font_config.OversampleV = 1`, this will largely reduce your texture size.
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!
2. You may reduce oversampling, e.g. `font_config.OversampleH = 2`, this will largely reduce your texture size.
Note that while OversampleH = 2 looks visibly very close to 3 in most situations, with OversampleH = 1 the quality drop will be noticeable.
3. Set `io.Fonts.TexDesiredWidth` to specify a texture width to minimize texture height (see comment in `ImFontAtlas::Build()` function).
4. Set `io.Fonts.Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;` to disable rounding the texture height to the next power of two.
5. Read about oversampling [here](https://github.com/nothings/stb/blob/master/tests/oversample).
6. To support the extended range of unicode beyond 0xFFFF (e.g. emoticons, dingbats, symbols, shapes, ancient languages, etc...) add `#define IMGUI_USE_WCHAR32`in your `imconfig.h`
6. To support the extended range of unicode beyond 0xFFFF (e.g. emoticons, dingbats, symbols, shapes, ancient languages, etc...) add `#define IMGUI_USE_WCHAR32`in your `imconfig.h`.
##### [Return to Index](#index)

View File

@ -20,7 +20,7 @@ Dear ImGui is designed to **enable fast iterations** and to **empower programmer
Dear ImGui is particularly suited to integration in games engine (for tooling), real-time 3D applications, fullscreen applications, embedded applications, or any applications on consoles platforms where operating system features are non-standard.
| [Usage](#usage) - [How it works](#how-it-works) - [Releases](#releases) - [Demo](#demo) - [Integration](#integration) |
| [Usage](#usage) - [How it works](#how-it-works) - [Releases & Changelogs](#releases--changelogs) - [Demo](#demo) - [Integration](#integration) |
:----------------------------------------------------------: |
| [Upcoming changes](#upcoming-changes) - [Gallery](#gallery) - [Support, FAQ](#support-frequently-asked-questions-faq) - [How to help](#how-to-help) - [Sponsors](#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) |
@ -52,8 +52,7 @@ Result:
Code:
```cpp
// Create a window called "My First Tool", with a menu bar.
if (!ImGui::Begin("My First Tool", &my_tool_active, ImGuiWindowFlags_MenuBar))
return;
ImGui::Begin("My First Tool", &my_tool_active, ImGuiWindowFlags_MenuBar);
if (ImGui::BeginMenuBar())
{
if (ImGui::BeginMenu("File"))
@ -94,9 +93,10 @@ Dear ImGui outputs vertex buffers and command lists that you can easily render i
_A common misunderstanding is to mistake immediate mode gui for immediate mode rendering, which usually implies hammering your driver/GPU with a bunch of inefficient draw calls and state changes as the gui functions are called. This is NOT what Dear ImGui does. Dear ImGui outputs vertex buffers and a small list of draw calls batches. It never touches your GPU directly. The draw call batches are decently optimal and you can render them later, in your app or even remotely._
### Releases
### Releases & Changelogs
See [Releases](https://github.com/ocornut/imgui/releases) page.
Reading the changelogs is a good way to keep up to date with the things Dear ImGui has to offer, and maybe will give you ideas of some features that you've been ignoring until now!
### Demo
@ -116,13 +116,13 @@ On most platforms and when using C++, **you should be able to use a combination
Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer at ease with those concepts, it should take you less than two hours to integrate Dear ImGui in your custom engine. **Make sure to spend time reading the [FAQ](https://www.dearimgui.org/faq), comments, and some of the examples/ application!**
Officially maintained backends/bindings (in repository):
- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, OpenGL (legacy), OpenGL3/ES/ES2 (modern), Vulkan, Metal.
- Platforms: GLFW, SDL2, Win32, Glut, OSX.
- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, Vulkan, WebGPU.
- Platforms: GLFW, SDL2, Win32, Glut, OSX, Android.
- Frameworks: Emscripten, Allegro5, Marmalade.
[Third-party backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) wiki page:
- Languages: C, C# and: Beef, ChaiScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift...
- Frameworks: AGS/Adventure Game Studio, Amethyst, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/Game Maker Studio2, Godot, GTK3+OpenGL3, Irrlicht Engine, LÖVE+LUA, Magnum, NanoRT, nCine, Nim Game Lib, Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, SFML, Sokol, Unity, Unreal Engine 4, vtk, Win32 GDI, WxWidgets.
- Languages: C, C# and: Beef, ChaiScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lobster, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift...
- Frameworks: AGS/Adventure Game Studio, Amethyst, Blender, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/Game Maker Studio2, GLEQ, Godot, GTK3+OpenGL3, Irrlicht Engine, LÖVE+LUA, Magnum, Monogame, NanoRT, nCine, Nim Game Lib, Nintendo 3DS & Switch (homebrew), Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, SDL_Renderer, SFML, Sokol, Unity, Unreal Engine 4, vtk, VulkanHpp, VulkanSceneGraph, Win32 GDI, WxWidgets.
- Note that C bindings ([cimgui](https://github.com/cimgui/cimgui)) are auto-generated, you can use its json/lua output to generate bindings for other languages.
[Useful widgets and extensions](https://github.com/ocornut/imgui/wiki/Useful-Widgets) wiki page:
@ -132,8 +132,7 @@ Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas.
### Upcoming Changes
Some of the goals for 2020 are:
- Work on new Tables API (to replace Columns). (see [#2957](https://github.com/ocornut/imgui/issues/2957), in public [tables](https://github.com/ocornut/imgui/tree/tables) branch looking for feedback)
Some of the goals for 2021 are:
- Work on Docking (see [#2109](https://github.com/ocornut/imgui/issues/2109), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch)
- Work on Multi-Viewport / Multiple OS windows. (see [#1542](https://github.com/ocornut/imgui/issues/1542), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch looking for feedback)
- Work on gamepad/keyboard controls. (see [#787](https://github.com/ocornut/imgui/issues/787))
@ -152,7 +151,7 @@ Custom engine
Custom engine
[![screenshot tool](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white_preview.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white.png)
[Tracy Profiler](https://bitbucket.org/wolfpld/tracy)
[Tracy Profiler](https://github.com/wolfpld/tracy)
![tracy profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v176/tracy_profiler.png)
### Support, Frequently Asked Questions (FAQ)
@ -163,9 +162,7 @@ See: [Wiki](https://github.com/ocornut/imgui/wiki) for many links, references, a
See: [Articles about the IMGUI paradigm](https://github.com/ocornut/imgui/wiki#about-the-imgui-paradigm) to read/learn about the Immediate Mode GUI paradigm.
If you are new to Dear ImGui and have issues with: compiling, linking, adding fonts, wiring inputs, running or displaying Dear ImGui: you can use [Discord server](http://discord.dearimgui.org).
Otherwise, for any other questions, bug reports, requests, feedback, you may post on https://github.com/ocornut/imgui/issues. Please read and fill the New Issue template carefully.
For questions, bug reports, requests, feedback, you may post on [GitHub Issues](https://github.com/ocornut/imgui/issues) or [GitHub Discussions](https://github.com/ocornut/imgui/discussions). Please read and fill the New Issue template carefully.
Private support is available for paying business customers (E-mail: _contact @ dearimgui dot com_).
@ -184,7 +181,7 @@ How to help
**How can I help?**
- You may participate in the [Discord server](http://discord.dearimgui.org), [GitHub forum/issues](https://github.com/ocornut/imgui/issues).
- See [GitHub Forum/issues](https://github.com/ocornut/imgui/issues) and [Github Discussions](https://github.com/ocornut/imgui/discussions).
- You may help with development and submit pull requests! Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance forever. PR should be crafted both in the interest in the end-users and also to ease the maintainer into understanding and accepting it.
- See [Help wanted](https://github.com/ocornut/imgui/wiki/Help-Wanted) on the [Wiki](https://github.com/ocornut/imgui/wiki/) for some more ideas.
- Have your company financially support this project (please reach by e-mail)
@ -196,15 +193,16 @@ See [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors) page.
Sponsors
--------
Ongoing Dear ImGui development is financially supported by users and private sponsors, recently:
Ongoing Dear ImGui development is currently financially supported by users and private sponsors:
*Platinum-chocolate sponsors*
- [Blizzard](https://careers.blizzard.com/en-us/openings/engineering/all/all/all/1), [Google](https://github.com/google/filament), [Nvidia](https://developer.nvidia.com/nvidia-omniverse), [Ubisoft](https://montreal.ubisoft.com/en/ubisoft-sponsors-user-interface-library-for-c-dear-imgui/)
*Double-chocolate and Salty caramel sponsors*
- [Activision](https://careers.activision.com/c/programmingsoftware-engineering-jobs), [Arkane Studios](https://www.arkane-studios.com), [Dotemu](http://www.dotemu.com), [Framefield](http://framefield.com), [Grinding Gear Games](https://www.grindinggear.com), [Hexagon](https://hexagonxalt.com/the-technology/xalt-visualization), [Kylotonn](https://www.kylotonn.com), [Media Molecule](http://www.mediamolecule.com), [Mesh Consultants](https://www.meshconsultants.ca), [Mobigame](http://www.mobigame.net), [Nadeo](https://www.nadeo.com), [Next Level Games](https://www.nextlevelgames.com), [RAD Game Tools](http://www.radgametools.com/), [Supercell](http://www.supercell.com), [Remedy Entertainment](https://www.remedygames.com/), [Unit 2 Games](https://unit2games.com/)
- [Activision](https://careers.activision.com/c/programmingsoftware-engineering-jobs), [Aras Pranckevičius](https://aras-p.info), [Arkane Studios](https://www.arkane-studios.com), [Framefield](http://framefield.com), [Grinding Gear Games](https://www.grindinggear.com), [Kylotonn](https://www.kylotonn.com), [Next Level Games](https://www.nextlevelgames.com), [RAD Game Tools](http://www.radgametools.com/), [Supercell](http://www.supercell.com)
From November 2014 to December 2019, ongoing development has also been financially supported by its users on Patreon and through individual donations. Please see [detailed list of Dear ImGui supporters](https://github.com/ocornut/imgui/wiki/Sponsors).
Please see [detailed list of Dear ImGui supporters](https://github.com/ocornut/imgui/wiki/Sponsors) for past sponsors.
From November 2014 to December 2019, ongoing development has also been financially supported by its users on Patreon and through individual donations.
**THANK YOU to all past and present supporters for helping to keep this project alive and thriving!**

View File

@ -88,6 +88,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- input text: access public fields via a non-callback API e.g. InputTextGetState("xxx") that may return NULL if not active.
- input text: flag to disable live update of the user buffer (also applies to float/int text input) (#701)
- input text: hover tooltip could show unclamped text
- input text: support for INSERT key to toggle overwrite mode. currently disabled because stb_textedit behavior is unsatisfactory on multi-line. (#2863)
- input text: option to Tab after an Enter validation.
- input text: add ImGuiInputTextFlags_EnterToApply? (off #218)
- input text: easier ways to update buffer (from source char*) while owned. preserve some sort of cursor position for multi-line text.
@ -129,18 +130,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- group: IsHovered() after EndGroup() covers whole aabb rather than the intersection of individual items. Is that desirable?
- group: merge deactivation/activation within same group (fwd WasEdited flag). (#2550)
- columns: sizing policy (e.g. for each column: fixed size, %, fill, distribute default size among fills) (#513, #125)
- columns: add a conditional parameter to SetColumnOffset() (#513, #125)
- columns: headers. re-orderable. (#513, #125)
- columns: optional sorting modifiers (up/down), sort list so sorting can be done multi-criteria. notify user when sort order changed.
- columns: option to alternate background colors on odd/even scanlines.
- columns: allow columns to recurse.
- columns: allow a same columns set to be interrupted by e.g. CollapsingHeader and resume with columns in sync when moving them.
- columns: sizing is lossy when columns width is very small (default width may turn negative etc.)
- columns: separator function or parameter that works within the column (currently Separator() bypass all columns) (#125)
- columns: flag to add horizontal separator above/below)
- columns/layout: setup minimum line height (equivalent of automatically calling AlignFirstTextHeightToWidgets)
!- color: the color conversion helpers/types are a mess and needs sorting out.
- color: (api breaking) ImGui::ColorConvertXXX functions should be loose ImColorConvertXX to match imgui_internals.h
@ -163,36 +152,8 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- separator: width, thickness, centering (#1643)
- splitter: formalize the splitter idiom into an official api (we want to handle n-way split) (#319)
- docking: merge docking branch (#2109)
- docking: B: ordering currently held in tab bar should be implicitly held by windows themselves (also see #2304)
- docking: B- tab bar: the order/focus restoring code could be part of TabBar and not DockNode? (#8)
- docking: B~ rework code to be able to lazily create tab bar instance in a single place. The _Unsorted tab flag could be replacing a trailing-counter in DockNode?
- docking: B~ fully track windows/settings reference in dock nodes. perhaps find a representation that allows facilitate use of dock builder functions.
- docking: B~ Unreal style document system (requires low-level controls of dockspace serialization fork/copy/delete). this is mostly working but the DockBuilderXXX api are not exposed/finished.
- docking: B: when docking outer, perform size locking on neighbors nodes the same way we do it with splitters, so other nodes are not resized.
- docking: B~ central node resizing behavior incorrect.
- docking: B: changing title font/style per-window is not supported as dock nodes are created in NewFrame.
- docking: B- dock node inside its own viewports creates 1 temporary viewport per window on startup before ditching them (doesn't affect the user nor request platform windows to be created, but unnecessary)
- docking: B- resize sibling locking behavior may be less desirable if we merged same-axis sibling in a same node level?
- docking: B- single visible node part of a hidden split hierarchy (OnlyNodeWithWindows != NULL) should show a normal title bar (not a tab bar)
- docking: B~ SetNextWindowDock() calls (with conditional) -> defer everything to DockContextUpdate (repro: Documents->[X]Windows->Dock 1 elsewhere->Click Redock All
- docking: B~ tidy up tab list popup buttons features (available with manual tab-bar, see ImGuiTabBarFlags_NoTabListPopupButton code, not used by docking nodes)
- docking: B- SetNextWindowDockId(0) with a second Begin() in the frame will asserts
- docking: B: resize grip drawn in host window typically appears under scrollbar.
- docking: B: resize grip auto-resize on multiple node hierarchy doesn't make much sense or should be improved?
- docking: B- SetNextWindowFocus() doesn't seem to apply if the window is hidden this frame, need repro (#4)
- docking: B- resizing a dock tree small currently has glitches (overlapping collapse and close button, etc.)
- docking: B- dpi: look at interaction with the hi-dpi and multi-dpi stuff.
- docking: B- tab bar: appearing on first frame with a dumb layout would do less harm that not appearing? (when behind dynamic branch) or store titles + render in EndTabBar()
- docking: B- tab bar: make selected tab always shows its full title?
- docking: B- hide close button on single tab bar?
- docking: B- nav: design interactions so nav controls can dock/undock
- docking: B- dockspace: flag to lock the dock tree and/or sizes (ImGuiDockNodeFlags_Locked?)
- docking: B- reintroduce collapsing a floating dock node. also collapsing a docked dock node!
- docking: B- allow dragging a non-floating dock node by clicking on the title-bar-looking section (not just the collapse/menu button)
- docking: B- option to remember undocked window size? (instead of keeping their docked size) (relate to #2104)
- docking: C- nav: CTRL+TAB highlighting tabs shows the mismatch between focus-stack and tab-order (not visible in VS because it doesn't highlight the tabs)
- docking: C- after a dock/undock, the Scrollbar Status update in Begin() should use an updated e.g. size_y_for_scrollbars to avoid a 1 frame scrollbar flicker.
- dock: merge docking branch (#2109)
- dock: dock out from a collapsing header? would work nicely but need emitting window to keep submitting the code.
- tabs: "there is currently a problem because TabItem() will try to submit their own tooltip after 0.50 second, and this will have the effect of making your tooltip flicker once." -> tooltip priority work
- tabs: close button tends to overlap unsaved-document star
@ -225,12 +186,11 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- combo: flag for BeginCombo to not return true when unchanged (#1182)
- combo: a way/helper to customize the combo preview (#1658)
- combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203)
- listbox: refactor and clean the begin/end api
- listbox: multiple selection.
- listbox: unselect option (#1208)
- listbox: make it easier/more natural to implement range-select (need some sort of info/ref about the last clicked/focused item that user can translate to an index?) (wip stash)
- listbox: user may want to initial scroll to focus on the one selected value?
- listbox: expose hovered item for a basic ListBox
- listbox: expose hovered item for a simplified ListBox api
- listbox: keyboard navigation.
- listbox: disable capturing mouse wheel if the listbox has no scrolling. (#1681)
- listbox: scrolling should track modified selection.
@ -287,12 +247,14 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- style: gradients fill (#1223) ~ 2 bg colors for each fill? tricky with rounded shapes and using textures for corners.
- style editor: color child window height expressed in multiple of line height.
- log: improve logging of ArrowButton, ListBox, TabItem
- log: carry on indent / tree depth when opening a child window
- log: enabling log ends up pushing and growing vertices buffers because we don't distinguish layout vs render clipping
- log: have more control over the log scope (e.g. stop logging when leaving current tree node scope)
- log: be able to log anything (e.g. right-click on a window/tree-node, shows context menu? log into tty/file/clipboard)
- log: let user copy any window content to clipboard easily (CTRL+C on windows? while moving it? context menu?). code is commented because it fails with multiple Begin/End pairs.
- log: obsolete LogButtons() all together.
- log: LogButtons() options for specifying depth and/or hiding depth slider
- log: enabling log ends up pushing and growing vertices buffersbecause we don't distinguish layout vs render clipping
- filters: set a current filter that tree node can automatically query to hide themselves
- filters: handle wild-cards (with implicit leading/trailing *), reg-exprs
@ -392,20 +354,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame)
- focus: unable to use SetKeyboardFocusHere() on clipped widgets. (#787)
- viewport: make it possible to have no main/hosting viewport
- viewport: We set ImGuiViewportFlags_NoFocusOnAppearing in a way that is required for GLFW/SDL binding, but could be handled better without
on a custom e.g. Win32 bindings. It prevents newly dragged-out viewports from taking the focus, which makes ALT+F4 more ambiguous.
- viewport: not focusing newly undocked viewport means clicking back on previous one doesn't bring OS window to front.
- viewport: with platform decoration enabled, platform may force constraint (e.g. minimum size)
- viewport: use getfocus/setfocus api to synchronize imgui<>platform focus better (e.g imgui-side ctrl-tab can focus os window, OS initial setup and alt-tab can focus imgui window etc.)
- viewport: store per-viewport/monitor DPI in .ini file so an application reload or main window changing DPI on reload can be properly patched for.
- viewport: implicit/fallback Debug window can hog a zombie viewport (harmless, noisy?) > could at least clear out the reference on a per session basis?
- viewport: need to clarify how to use GetMousePos() from a user point of view.
- platform: glfw: no support for ImGuiBackendFlags_HasMouseHoveredViewport.
- platform: sdl: no support for ImGuiBackendFlags_HasMouseHoveredViewport. maybe we could use SDL_GetMouseFocus() / SDL_WINDOW_MOUSE_FOCUS if imgui could fallback on its heuristic when NoInputs is set
- platform: sdl: no refresh of monitor/display (SDL doesn't seem to have an event for it).
- platform: sdl: multi-viewport + minimized window seems to break mouse wheel events (at least under Win32).
- inputs: we need an explicit flag about whether the imgui window is focused, to be able to distinguish focused key releases vs alt-tabbing all release behaviors.
- inputs: rework IO system to be able to pass actual ordered/timestamped events. use an event queue? (~#335, #71)
- inputs: support track pad style scrolling & slider edit.

View File

@ -171,7 +171,7 @@
<ClInclude Include="..\..\backends\imgui_impl_allegro5.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\misc\natvis\imgui.natvis" />
<None Include="..\..\misc\debuggers\imgui.natvis" />
<None Include="..\README.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -51,7 +51,7 @@
</ItemGroup>
<ItemGroup>
<None Include="..\README.txt" />
<None Include="..\..\misc\natvis\imgui.natvis">
<None Include="..\..\misc\debuggers\imgui.natvis">
<Filter>sources</Filter>
</None>
</ItemGroup>

View File

@ -28,7 +28,6 @@ int main(int, char**)
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
// Setup Dear ImGui style
ImGui::StyleColorsDark();
@ -122,7 +121,7 @@ int main(int, char**)
// Rendering
ImGui::Render();
al_clear_to_color(al_map_rgba_f(clear_color.x, clear_color.y, clear_color.z, clear_color.w));
al_clear_to_color(al_map_rgba_f(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w));
ImGui_ImplAllegro5_RenderDrawData(ImGui::GetDrawData());
al_flip_display();
}

View File

@ -0,0 +1,40 @@
cmake_minimum_required(VERSION 3.6)
project(ImGuiExample)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
add_library(${CMAKE_PROJECT_NAME} SHARED
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../../imgui.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../../imgui_demo.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../../imgui_draw.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../../imgui_tables.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../../imgui_widgets.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../../backends/imgui_impl_android.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../../backends/imgui_impl_opengl3.cpp
${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c
)
set(CMAKE_SHARED_LINKER_FLAGS
"${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate"
)
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE
IMGUI_IMPL_OPENGL_ES3
)
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/../..
${CMAKE_CURRENT_SOURCE_DIR}/../../backends
${ANDROID_NDK}/sources/android/native_app_glue
)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
android
EGL
GLESv3
log
)

View File

@ -0,0 +1,12 @@
.cxx
.externalNativeBuild
build/
*.iml
.idea
.gradle
local.properties
# Android Studio puts a Gradle wrapper here, that we don't want:
gradle/
gradlew*

View File

@ -0,0 +1,34 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 29
buildToolsVersion "30.0.3"
ndkVersion "21.4.7075529"
defaultConfig {
applicationId "imgui.example.android"
minSdkVersion 23
targetSdkVersion 29
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
}
}
externalNativeBuild {
cmake {
path "../../CMakeLists.txt"
}
}
}
repositories {
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="imgui.example.android">
<application
android:label="ImGuiExample"
android:allowBackup="false"
android:fullBackupContent="false"
android:hasCode="true">
<activity
android:name="imgui.example.android.MainActivity"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:configChanges="orientation|keyboardHidden|screenSize">
<meta-data android:name="android.app.lib_name"
android:value="ImGuiExample" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -0,0 +1,40 @@
package imgui.example.android
import android.app.NativeActivity
import android.os.Bundle
import android.content.Context
import android.view.inputmethod.InputMethodManager
import android.view.KeyEvent
import java.util.concurrent.LinkedBlockingQueue
class MainActivity : NativeActivity() {
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
fun showSoftInput() {
val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.showSoftInput(this.window.decorView, 0)
}
fun hideSoftInput() {
val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(this.window.decorView.windowToken, 0)
}
// Queue for the Unicode characters to be polled from native code (via pollUnicodeChar())
private var unicodeCharacterQueue: LinkedBlockingQueue<Int> = LinkedBlockingQueue()
// We assume dispatchKeyEvent() of the NativeActivity is actually called for every
// KeyEvent and not consumed by any View before it reaches here
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
if (event.action == KeyEvent.ACTION_DOWN) {
unicodeCharacterQueue.offer(event.getUnicodeChar(event.metaState))
}
return super.dispatchKeyEvent(event)
}
fun pollUnicodeChar(): Int {
return unicodeCharacterQueue.poll() ?: 0
}
}

View File

@ -0,0 +1,24 @@
buildscript {
ext.kotlin_version = '1.4.30'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

View File

@ -0,0 +1 @@
include ':app'

View File

@ -0,0 +1,369 @@
// dear imgui: standalone example application for Android + OpenGL ES 3
// If you are new to dear imgui, see examples/README.txt and documentation at the top of imgui.cpp.
#include "imgui.h"
#include "imgui_impl_android.h"
#include "imgui_impl_opengl3.h"
#include <android/log.h>
#include <android_native_app_glue.h>
#include <android/asset_manager.h>
#include <EGL/egl.h>
#include <GLES3/gl3.h>
// Data
static EGLDisplay g_EglDisplay = EGL_NO_DISPLAY;
static EGLSurface g_EglSurface = EGL_NO_SURFACE;
static EGLContext g_EglContext = EGL_NO_CONTEXT;
static struct android_app* g_App = NULL;
static bool g_Initialized = false;
static char g_LogTag[] = "ImGuiExample";
// Forward declarations of helper functions
static int ShowSoftKeyboardInput();
static int PollUnicodeChars();
static int GetAssetData(const char* filename, void** out_data);
void init(struct android_app* app)
{
if (g_Initialized)
return;
g_App = app;
ANativeWindow_acquire(g_App->window);
// Initialize EGL
// This is mostly boilerplate code for EGL...
{
g_EglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (g_EglDisplay == EGL_NO_DISPLAY)
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s", "eglGetDisplay(EGL_DEFAULT_DISPLAY) returned EGL_NO_DISPLAY");
if (eglInitialize(g_EglDisplay, 0, 0) != EGL_TRUE)
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s", "eglInitialize() returned with an error");
const EGLint egl_attributes[] = { EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_DEPTH_SIZE, 24, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE };
EGLint num_configs = 0;
if (eglChooseConfig(g_EglDisplay, egl_attributes, nullptr, 0, &num_configs) != EGL_TRUE)
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s", "eglChooseConfig() returned with an error");
if (num_configs == 0)
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s", "eglChooseConfig() returned 0 matching config");
// Get the first matching config
EGLConfig egl_config;
eglChooseConfig(g_EglDisplay, egl_attributes, &egl_config, 1, &num_configs);
EGLint egl_format;
eglGetConfigAttrib(g_EglDisplay, egl_config, EGL_NATIVE_VISUAL_ID, &egl_format);
ANativeWindow_setBuffersGeometry(g_App->window, 0, 0, egl_format);
const EGLint egl_context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE };
g_EglContext = eglCreateContext(g_EglDisplay, egl_config, EGL_NO_CONTEXT, egl_context_attributes);
if (g_EglContext == EGL_NO_CONTEXT)
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s", "eglCreateContext() returned EGL_NO_CONTEXT");
g_EglSurface = eglCreateWindowSurface(g_EglDisplay, egl_config, g_App->window, NULL);
eglMakeCurrent(g_EglDisplay, g_EglSurface, g_EglSurface, g_EglContext);
}
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
// Disable loading/saving of .ini file from disk.
// FIXME: Consider using LoadIniSettingsFromMemory() / SaveIniSettingsToMemory() to save in appropriate location for Android.
io.IniFilename = NULL;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
// Setup Platform/Renderer backends
ImGui_ImplAndroid_Init(g_App->window);
ImGui_ImplOpenGL3_Init("#version 300 es");
// 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 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).
// - 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.
// - Read 'docs/FONTS.md' for more instructions and details.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
// - Android: The TTF files have to be placed into the assets/ directory (android/app/src/main/assets), we use our GetAssetData() helper to retrieve them.
// We load the default font with increased size to improve readability on many devices with "high" DPI.
// FIXME: Put some effort into DPI awareness.
// Important: when calling AddFontFromMemoryTTF(), ownership of font_data is transfered by Dear ImGui by default (deleted is handled by Dear ImGui), unless we set FontDataOwnedByAtlas=false in ImFontConfig
ImFontConfig font_cfg;
font_cfg.SizePixels = 22.0f;
io.Fonts->AddFontDefault(&font_cfg);
//void* font_data;
//int font_data_size;
//ImFont* font;
//font_data_size = GetAssetData("Roboto-Medium.ttf", &font_data);
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 16.0f);
//IM_ASSERT(font != NULL);
//font_data_size = GetAssetData("Cousine-Regular.ttf", &font_data);
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 15.0f);
//IM_ASSERT(font != NULL);
//font_data_size = GetAssetData("DroidSans.ttf", &font_data);
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 16.0f);
//IM_ASSERT(font != NULL);
//font_data_size = GetAssetData("ProggyTiny.ttf", &font_data);
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 10.0f);
//IM_ASSERT(font != NULL);
//font_data_size = GetAssetData("ArialUni.ttf", &font_data);
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
// Arbitrary scale-up
// FIXME: Put some effort into DPI awareness
ImGui::GetStyle().ScaleAllSizes(3.0f);
g_Initialized = true;
}
void tick()
{
ImGuiIO& io = ImGui::GetIO();
if (g_EglDisplay == EGL_NO_DISPLAY)
return;
// Our state
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);
// Poll Unicode characters via JNI
// FIXME: do not call this every frame because of JNI overhead
PollUnicodeChars();
// Open on-screen (soft) input if requested by Dear ImGui
static bool WantTextInputLast = false;
if (io.WantTextInput && !WantTextInputLast)
ShowSoftKeyboardInput();
WantTextInputLast = io.WantTextInput;
// Start the Dear ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplAndroid_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 created 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 / ImGui::GetIO().Framerate, ImGui::GetIO().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();
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
eglSwapBuffers(g_EglDisplay, g_EglSurface);
}
void shutdown()
{
if (!g_Initialized)
return;
// Cleanup
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplAndroid_Shutdown();
ImGui::DestroyContext();
if (g_EglDisplay != EGL_NO_DISPLAY)
{
eglMakeCurrent(g_EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (g_EglContext != EGL_NO_CONTEXT)
eglDestroyContext(g_EglDisplay, g_EglContext);
if (g_EglSurface != EGL_NO_SURFACE)
eglDestroySurface(g_EglDisplay, g_EglSurface);
eglTerminate(g_EglDisplay);
}
g_EglDisplay = EGL_NO_DISPLAY;
g_EglContext = EGL_NO_CONTEXT;
g_EglSurface = EGL_NO_SURFACE;
ANativeWindow_release(g_App->window);
g_Initialized = false;
}
static void handleAppCmd(struct android_app* app, int32_t appCmd)
{
switch (appCmd)
{
case APP_CMD_SAVE_STATE:
break;
case APP_CMD_INIT_WINDOW:
init(app);
break;
case APP_CMD_TERM_WINDOW:
shutdown();
break;
case APP_CMD_GAINED_FOCUS:
break;
case APP_CMD_LOST_FOCUS:
break;
}
}
static int32_t handleInputEvent(struct android_app* app, AInputEvent* inputEvent)
{
return ImGui_ImplAndroid_HandleInputEvent(inputEvent);
}
void android_main(struct android_app* app)
{
app->onAppCmd = handleAppCmd;
app->onInputEvent = handleInputEvent;
while (true)
{
int out_events;
struct android_poll_source* out_data;
// Poll all events. If the app is not visible, this loop blocks until g_Initialized == true.
while (ALooper_pollAll(g_Initialized ? 0 : -1, NULL, &out_events, (void**)&out_data) >= 0)
{
// Process one event
if (out_data != NULL)
out_data->process(app, out_data);
// Exit the app by returning from within the infinite loop
if (app->destroyRequested != 0)
{
// shutdown() should have been called already while processing the
// app command APP_CMD_TERM_WINDOW. But we play save here
if (!g_Initialized)
shutdown();
return;
}
}
// Initiate a new frame
tick();
}
}
// Unfortunately, there is no way to show the on-screen input from native code.
// Therefore, we call ShowSoftKeyboardInput() of the main activity implemented in MainActivity.kt via JNI.
static int ShowSoftKeyboardInput()
{
JavaVM* java_vm = g_App->activity->vm;
JNIEnv* java_env = NULL;
jint jni_return = java_vm->GetEnv((void**)&java_env, JNI_VERSION_1_6);
if (jni_return == JNI_ERR)
return -1;
jni_return = java_vm->AttachCurrentThread(&java_env, NULL);
if (jni_return != JNI_OK)
return -2;
jclass native_activity_clazz = java_env->GetObjectClass(g_App->activity->clazz);
if (native_activity_clazz == NULL)
return -3;
jmethodID method_id = java_env->GetMethodID(native_activity_clazz, "showSoftInput", "()V");
if (method_id == NULL)
return -4;
java_env->CallVoidMethod(g_App->activity->clazz, method_id);
jni_return = java_vm->DetachCurrentThread();
if (jni_return != JNI_OK)
return -5;
return 0;
}
// Unfortunately, the native KeyEvent implementation has no getUnicodeChar() function.
// Therefore, we implement the processing of KeyEvents in MainActivity.kt and poll
// the resulting Unicode characters here via JNI and send them to Dear ImGui.
static int PollUnicodeChars()
{
JavaVM* java_vm = g_App->activity->vm;
JNIEnv* java_env = NULL;
jint jni_return = java_vm->GetEnv((void**)&java_env, JNI_VERSION_1_6);
if (jni_return == JNI_ERR)
return -1;
jni_return = java_vm->AttachCurrentThread(&java_env, NULL);
if (jni_return != JNI_OK)
return -2;
jclass native_activity_clazz = java_env->GetObjectClass(g_App->activity->clazz);
if (native_activity_clazz == NULL)
return -3;
jmethodID method_id = java_env->GetMethodID(native_activity_clazz, "pollUnicodeChar", "()I");
if (method_id == NULL)
return -4;
// Send the actual characters to Dear ImGui
ImGuiIO& io = ImGui::GetIO();
jint unicode_character;
while ((unicode_character = java_env->CallIntMethod(g_App->activity->clazz, method_id)) != 0)
io.AddInputCharacter(unicode_character);
jni_return = java_vm->DetachCurrentThread();
if (jni_return != JNI_OK)
return -5;
return 0;
}
// Helper to retrieve data placed into the assets/ directory (android/app/src/main/assets)
static int GetAssetData(const char* filename, void** outData)
{
int num_bytes = 0;
AAsset* asset_descriptor = AAssetManager_open(g_App->activity->assetManager, filename, AASSET_MODE_BUFFER);
if (asset_descriptor)
{
num_bytes = AAsset_getLength(asset_descriptor);
*outData = IM_ALLOC(num_bytes);
int64_t num_bytes_read = AAsset_read(asset_descriptor, *outData, num_bytes);
AAsset_close(asset_descriptor);
IM_ASSERT(num_bytes_read == num_bytes);
}
return num_bytes;
}

View File

@ -245,7 +245,7 @@
MTLRenderPassDescriptor* renderPassDescriptor = view.currentRenderPassDescriptor;
if (renderPassDescriptor != nil)
{
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0] * clear_color[3], clear_color[1] * clear_color[3], clear_color[2] * clear_color[3], clear_color[3]);
// Here, you could do additional rendering work, including other passes as necessary.

View File

@ -97,7 +97,7 @@
GLsizei height = (GLsizei)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
glViewport(0, 0, width, height);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL2_RenderDrawData(draw_data);
@ -250,7 +250,6 @@
ImGuiIO& io = ImGui::GetIO(); (void)io;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
// Setup Dear ImGui style
ImGui::StyleColorsDark();

View File

@ -7,15 +7,16 @@
# (On Windows, you may need to execute emsdk_env.bat or encmdprompt.bat ahead)
#
# Running `make` will produce three files:
# - example_emscripten_opengl3.html
# - example_emscripten_opengl3.js
# - example_emscripten_opengl3.wasm
# - web/index.html
# - web/index.js
# - web/index.wasm
#
# All three are needed to run the demo.
CC = emcc
CXX = em++
EXE = example_emscripten_opengl3.html
WEB_DIR = web
EXE = $(WEB_DIR)/index.html
IMGUI_DIR = ../..
SOURCES = main.cpp
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
@ -78,8 +79,14 @@ LDFLAGS += --shell-file shell_minimal.html
all: $(EXE)
@echo Build complete for $(EXE)
$(EXE): $(OBJS)
$(CXX) -o $@ $^ $(LIBS) $(LDFLAGS)
$(WEB_DIR):
mkdir $@
serve: all
python3 -m http.server -d $(WEB_DIR)
$(EXE): $(OBJS) $(WEB_DIR)
$(CXX) -o $@ $(OBJS) $(LIBS) $(LDFLAGS)
clean:
rm -f $(EXE) $(OBJS) *.js *.wasm *.wasm.pre
rm -rf $(OBJS) $(WEB_DIR)

View File

@ -1,4 +1,3 @@
## How to Build
- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
@ -9,10 +8,13 @@
## How to Run
To run on a local machine:
- Generally you may need a local webserver. Quoting [https://emscripten.org/docs/getting_started](https://emscripten.org/docs/getting_started/Tutorial.html#generating-html):<br>
- `make serve` will use Python3 to spawn a local webserver, you can then browse http://localhost:8000 to access your build.
- Otherwise, generally you will need a local webserver:
- Quoting [https://emscripten.org/docs/getting_started](https://emscripten.org/docs/getting_started/Tutorial.html#generating-html):<br>
_"Unfortunately several browsers (including Chrome, Safari, and Internet Explorer) do not support file:// [XHR](https://emscripten.org/docs/site/glossary.html#term-xhr) requests, and cant load extra files needed by the HTML (like a .wasm file, or packaged file data as mentioned lower down). For these browsers youll need to serve the files using a [local webserver](https://emscripten.org/docs/getting_started/FAQ.html#faq-local-webserver) and then open http://localhost:8000/hello.html."_
- Emscripten SDK has a handy `emrun` command: `emrun example_emscripten_opengl3.html` which will spawn a temporary local webserver. See https://emscripten.org/docs/compiling/Running-html-files-with-emrun.html for details.
- Otherwise you may use Python builtin webserver: `python -m http.server` in Python 3 or `python -m SimpleHTTPServer` in Python 2. After doing that, you can visit http://localhost:8000/.
- Emscripten SDK has a handy `emrun` command: `emrun web/example_emscripten_opengl3.html --browser firefox` which will spawn a temporary local webserver (in Firefox). See https://emscripten.org/docs/compiling/Running-html-files-with-emrun.html for details.
- You may use Python 3 builtin webserver: `python -m http.server -d web` (this is what `make serve` uses).
- You may use Python 2 builtin webserver: `cd web && python -m SimpleHTTPServer`.
## Obsolete features:

View File

@ -21,7 +21,7 @@ SDL_Window* g_Window = NULL;
SDL_GLContext g_GLContext = NULL;
// For clarity, our main loop code is declared at the end.
void main_loop(void*);
static void main_loop(void*);
int main(int, char**)
{
@ -62,9 +62,8 @@ int main(int, char**)
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
// 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.
@ -100,7 +99,7 @@ int main(int, char**)
emscripten_set_main_loop_arg(main_loop, NULL, 0, true);
}
void main_loop(void* arg)
static void main_loop(void* arg)
{
ImGuiIO& io = ImGui::GetIO();
IM_UNUSED(arg); // We can pass this argument as the second parameter of emscripten_set_main_loop_arg(), but we don't use that.
@ -168,7 +167,7 @@ void main_loop(void* arg)
ImGui::Render();
SDL_GL_MakeCurrent(g_Window, g_GLContext);
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
SDL_GL_SwapWindow(g_Window);

View File

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

View File

@ -0,0 +1,10 @@
# How to Build
- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
- Depending on your configuration, in Windows you may need to run `emsdk/emsdk_env.bat` in your console to access the Emscripten command-line tools.
- Then build using `make` while in the `example_emscripten_wgpu/` directory.
- Requires Emscripten 2.0.10 (December 2020) due to GLFW adaptations

View File

@ -0,0 +1,245 @@
// Dear ImGui: standalone example application for Emscripten, using GLFW + WebGPU
// (Emscripten is a C++-to-javascript compiler, used to publish executables for the web. See https://emscripten.org/)
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_wgpu.h"
#include <stdio.h>
#include <emscripten.h>
#include <emscripten/html5.h>
#include <emscripten/html5_webgpu.h>
#include <GLFW/glfw3.h>
#include <webgpu/webgpu.h>
#include <webgpu/webgpu_cpp.h>
// Global WebGPU required states
static WGPUDevice wgpu_device = NULL;
static WGPUSurface wgpu_surface = NULL;
static WGPUSwapChain wgpu_swap_chain = NULL;
static int wgpu_swap_chain_width = 0;
static int wgpu_swap_chain_height = 0;
// States tracked across render frames
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);
// Forward declarations
static bool init_wgpu();
static void main_loop(void* window);
static void print_glfw_error(int error, const char* description);
static void print_wgpu_error(WGPUErrorType error_type, const char* message, void*);
int main(int, char**)
{
glfwSetErrorCallback(print_glfw_error);
if (!glfwInit())
return 1;
// Make sure GLFW does not initialize any graphics context.
// This needs to be done explicitly later
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+WebGPU example", NULL, NULL);
if (!window)
{
glfwTerminate();
return 1;
}
// Initialize the WebGPU environment
if (!init_wgpu())
{
if (window)
glfwDestroyWindow(window);
glfwTerminate();
return 1;
}
glfwShowWindow(window);
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
// For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file.
// You may manually call LoadIniSettingsFromMemory() to load settings from your own storage.
io.IniFilename = NULL;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
// Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForOther(window, true);
ImGui_ImplWGPU_Init(wgpu_device, 3, WGPUTextureFormat_RGBA8Unorm);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - 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.
// - Read 'docs/FONTS.md' for more instructions and details.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
// - Emscripten allows preloading a file or folder to be accessible at runtime. See Makefile for details.
//io.Fonts->AddFontDefault();
#ifndef IMGUI_DISABLE_FILE_FUNCTIONS
io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("fonts/ProggyTiny.ttf", 10.0f);
//ImFont* font = io.Fonts->AddFontFromFileTTF("fonts/ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
#endif
// This function will directly return and exit the main function.
// Make sure that no required objects get cleaned up.
// This way we can use the browsers 'requestAnimationFrame' to control the rendering.
emscripten_set_main_loop_arg(main_loop, window, 0, false);
return 0;
}
static bool init_wgpu()
{
wgpu_device = emscripten_webgpu_get_device();
if (!wgpu_device)
return false;
wgpuDeviceSetUncapturedErrorCallback(wgpu_device, print_wgpu_error, NULL);
// Use C++ wrapper due to misbehavior in Emscripten.
// Some offset computation for wgpuInstanceCreateSurface in JavaScript
// seem to be inline with struct alignments in the C++ structure
wgpu::SurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
html_surface_desc.selector = "#canvas";
wgpu::SurfaceDescriptor surface_desc = {};
surface_desc.nextInChain = &html_surface_desc;
// Use 'null' instance
wgpu::Instance instance = {};
wgpu_surface = instance.CreateSurface(&surface_desc).Release();
return true;
}
static void main_loop(void* window)
{
glfwPollEvents();
int width, height;
glfwGetFramebufferSize((GLFWwindow*) window, &width, &height);
// React to changes in screen size
if (width != wgpu_swap_chain_width && height != wgpu_swap_chain_height)
{
ImGui_ImplWGPU_InvalidateDeviceObjects();
if (wgpu_swap_chain)
wgpuSwapChainRelease(wgpu_swap_chain);
wgpu_swap_chain_width = width;
wgpu_swap_chain_height = height;
WGPUSwapChainDescriptor swap_chain_desc = {};
swap_chain_desc.usage = WGPUTextureUsage_OutputAttachment;
swap_chain_desc.format = WGPUTextureFormat_RGBA8Unorm;
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();
// 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 created 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 / ImGui::GetIO().Framerate, ImGui::GetIO().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();
WGPURenderPassColorAttachmentDescriptor color_attachments = {};
color_attachments.loadOp = WGPULoadOp_Clear;
color_attachments.storeOp = WGPUStoreOp_Store;
color_attachments.clearColor = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
color_attachments.attachment = wgpuSwapChainGetCurrentTextureView(wgpu_swap_chain);
WGPURenderPassDescriptor render_pass_desc = {};
render_pass_desc.colorAttachmentCount = 1;
render_pass_desc.colorAttachments = &color_attachments;
render_pass_desc.depthStencilAttachment = NULL;
WGPUCommandEncoderDescriptor enc_desc = {};
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(wgpu_device, &enc_desc);
WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(encoder, &render_pass_desc);
ImGui_ImplWGPU_RenderDrawData(ImGui::GetDrawData(), pass);
wgpuRenderPassEncoderEndPass(pass);
WGPUCommandBufferDescriptor cmd_buffer_desc = {};
WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc);
WGPUQueue queue = wgpuDeviceGetDefaultQueue(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

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

View File

@ -99,7 +99,7 @@ int main(int, char**)
id<CAMetalDrawable> drawable = [layer nextDrawable];
id<MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer];
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0] * clear_color[3], clear_color[1] * clear_color[3], clear_color[2] * clear_color[3], clear_color[3]);
renderPassDescriptor.colorAttachments[0].texture = drawable.texture;
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;

View File

@ -49,7 +49,7 @@ ifeq ($(UNAME_S), Darwin) #APPLE
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(findstring MINGW,$(UNAME_S)),MINGW)
ifeq ($(OS), Windows_NT)
ECHO_MESSAGE = "MinGW"
LIBS += -lglfw3 -lgdi32 -lopengl32 -limm32

View File

@ -1,3 +1,8 @@
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
mkdir Debug
cl /nologo /Zi /MD /I .. /I ..\.. /I ..\libs\glfw\include *.cpp ..\..\backends\imgui_impl_opengl2.cpp ..\..\backends\imgui_impl_glfw.cpp ..\..\imgui*.cpp /FeDebug/example_glfw_opengl2.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 glfw3.lib opengl32.lib gdi32.lib shell32.lib
@set OUT_DIR=Debug
@set OUT_EXE=example_glfw_opengl2
@set INCLUDES=/I..\.. /I..\..\backends /I..\libs\glfw\include
@set SOURCES=main.cpp ..\..\backends\imgui_impl_opengl2.cpp ..\..\backends\imgui_impl_glfw.cpp ..\..\imgui*.cpp
@set LIBS=/LIBPATH:..\libs\glfw\lib-vc2010-32 glfw3.lib opengl32.lib gdi32.lib shell32.lib
mkdir %OUT_DIR%
cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%

View File

@ -172,7 +172,7 @@
<ClInclude Include="..\..\backends\imgui_impl_opengl2.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\misc\natvis\imgui.natvis" />
<None Include="..\..\misc\debuggers\imgui.natvis" />
<None Include="..\README.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -54,7 +54,7 @@
</ItemGroup>
<ItemGroup>
<None Include="..\README.txt" />
<None Include="..\..\misc\natvis\imgui.natvis">
<None Include="..\..\misc\debuggers\imgui.natvis">
<Filter>sources</Filter>
</None>
</ItemGroup>

View File

@ -44,25 +44,13 @@ int main(int, char**)
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigViewportsNoAutoMerge = true;
//io.ConfigViewportsNoTaskBarIcon = true;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
ImGuiStyle& style = ImGui::GetStyle();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
}
// Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL2_Init();
@ -144,28 +132,18 @@ int main(int, char**)
int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
// If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
// you may need to backup/reset/restore current shader using the commented lines below.
// you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below.
//GLint last_program;
//glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
//glUseProgram(0);
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
//glUseProgram(last_program);
// Update and Render additional Platform Windows
// (Platform functions may change the current OpenGL context, so we save/restore it to make it easier to paste this code elsewhere.
// For this specific demo app we could also call glfwMakeContextCurrent(window) directly)
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
GLFWwindow* backup_current_context = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
glfwMakeContextCurrent(backup_current_context);
}
glfwMakeContextCurrent(window);
glfwSwapBuffers(window);
}

View File

@ -79,7 +79,7 @@ ifeq ($(UNAME_S), Darwin) #APPLE
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(findstring MINGW,$(UNAME_S)),MINGW)
ifeq ($(OS), Windows_NT)
ECHO_MESSAGE = "MinGW"
LIBS += -lglfw3 -lgdi32 -lopengl32 -limm32

View File

@ -1,3 +1,8 @@
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
mkdir Debug
cl /nologo /Zi /MD /I .. /I ..\.. /I ..\libs\glfw\include /I ..\libs\gl3w *.cpp ..\..\backends\imgui_impl_glfw.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c /FeDebug/example_glfw_opengl3.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 glfw3.lib opengl32.lib gdi32.lib shell32.lib
@set OUT_DIR=Debug
@set OUT_EXE=example_glfw_opengl3
@set INCLUDES=/I..\.. /I..\..\backends /I..\libs\glfw\include /I..\libs\gl3w
@set SOURCES=main.cpp ..\..\backends\imgui_impl_glfw.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c
@set LIBS=/LIBPATH:..\libs\glfw\lib-vc2010-32 glfw3.lib opengl32.lib gdi32.lib shell32.lib
mkdir %OUT_DIR%
cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%

View File

@ -175,7 +175,7 @@
<ClInclude Include="..\libs\gl3w\GL\glcorearb.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\misc\natvis\imgui.natvis" />
<None Include="..\..\misc\debuggers\imgui.natvis" />
<None Include="..\README.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -66,7 +66,7 @@
</ItemGroup>
<ItemGroup>
<None Include="..\README.txt" />
<None Include="..\..\misc\natvis\imgui.natvis">
<None Include="..\..\misc\debuggers\imgui.natvis">
<Filter>sources</Filter>
</None>
</ItemGroup>

View File

@ -108,25 +108,13 @@ int main(int, char**)
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigViewportsNoAutoMerge = true;
//io.ConfigViewportsNoTaskBarIcon = true;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
ImGuiStyle& style = ImGui::GetStyle();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
}
// Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init(glsl_version);
@ -208,20 +196,9 @@ int main(int, char**)
int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
// Update and Render additional Platform Windows
// (Platform functions may change the current OpenGL context, so we save/restore it to make it easier to paste this code elsewhere.
// For this specific demo app we could also call glfwMakeContextCurrent(window) directly)
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
GLFWwindow* backup_current_context = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
glfwMakeContextCurrent(backup_current_context);
}
glfwSwapBuffers(window);
}

View File

@ -1,7 +1,14 @@
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
mkdir Debug
cl /nologo /Zi /MD /I .. /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\backends\imgui_impl_glfw.cpp ..\..\imgui*.cpp /FeDebug/example_glfw_vulkan.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\lib32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
@set OUT_EXE=example_glfw_vulkan
@set INCLUDES=/I..\.. /I..\..\backends /I..\libs\glfw\include /I %VULKAN_SDK%\include
@set SOURCES=main.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\backends\imgui_impl_glfw.cpp ..\..\imgui*.cpp
@set LIBS=/LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\lib32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
mkdir Release
cl /nologo /Zi /MD /Ox /Oi /I .. /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\backends\imgui_impl_glfw.cpp ..\..\imgui*.cpp /FeRelease/example_glfw_vulkan.exe /FoRelease/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\lib32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
@set OUT_DIR=Debug
mkdir %OUT_DIR%
cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
@set OUT_DIR=Release
mkdir %OUT_DIR%
cl /nologo /Zi /MD /Ox /Oi %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%

View File

@ -1,7 +1,13 @@
@REM Build for Visual Studio compiler. Run your copy of amd64/vcvars32.bat to setup 64-bit command-line compiler.
mkdir Debug
cl /nologo /Zi /MD /I .. /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\backends\imgui_impl_glfw.cpp ..\..\imgui*.cpp /FeDebug/example_glfw_vulkan.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-64 /libpath:%VULKAN_SDK%\lib glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
@set INCLUDES=/I..\.. /I..\..\backends /I..\libs\glfw\include /I %VULKAN_SDK%\include
@set SOURCES=main.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\backends\imgui_impl_glfw.cpp ..\..\imgui*.cpp
@set LIBS=/LIBPATH:..\libs\glfw\lib-vc2010-64 /libpath:%VULKAN_SDK%\lib glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
mkdir Release
cl /nologo /Zi /MD /Ox /Oi /I .. /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\backends\imgui_impl_glfw.cpp ..\..\imgui*.cpp /FeRelease/example_glfw_vulkan.exe /FoRelease/ /link /LIBPATH:..\libs\glfw\lib-vc2010-64 /libpath:%VULKAN_SDK%\lib glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
@set OUT_DIR=Debug
mkdir %OUT_DIR%
cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
@set OUT_DIR=Release
mkdir %OUT_DIR%
cl /nologo /Zi /MD /Ox /Oi %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%

View File

@ -172,7 +172,7 @@
<ClInclude Include="..\..\backends\imgui_impl_vulkan.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\misc\natvis\imgui.natvis" />
<None Include="..\..\misc\debuggers\imgui.natvis" />
<None Include="..\README.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -54,7 +54,7 @@
</ItemGroup>
<ItemGroup>
<None Include="..\README.txt" />
<None Include="..\..\misc\natvis\imgui.natvis">
<None Include="..\..\misc\debuggers\imgui.natvis">
<Filter>sources</Filter>
</None>
</ItemGroup>

View File

@ -375,25 +375,13 @@ int main(int, char**)
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigViewportsNoAutoMerge = true;
//io.ConfigViewportsNoTaskBarIcon = true;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
ImGuiStyle& style = ImGui::GetStyle();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
}
// Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForVulkan(window, true);
ImGui_ImplVulkan_InitInfo init_info = {};
@ -528,22 +516,17 @@ int main(int, char**)
// Rendering
ImGui::Render();
ImDrawData* main_draw_data = ImGui::GetDrawData();
const bool main_is_minimized = (main_draw_data->DisplaySize.x <= 0.0f || main_draw_data->DisplaySize.y <= 0.0f);
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
if (!main_is_minimized)
FrameRender(wd, main_draw_data);
// Update and Render additional Platform Windows
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImDrawData* draw_data = ImGui::GetDrawData();
const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f);
if (!is_minimized)
{
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
}
// Present Main Platform Window
if (!main_is_minimized)
wd->ClearValue.color.float32[0] = clear_color.x * clear_color.w;
wd->ClearValue.color.float32[1] = clear_color.y * clear_color.w;
wd->ClearValue.color.float32[2] = clear_color.z * clear_color.w;
wd->ClearValue.color.float32[3] = clear_color.w;
FrameRender(wd, draw_data);
FramePresent(wd);
}
}
// Cleanup

View File

@ -40,7 +40,7 @@ ifeq ($(UNAME_S), Darwin) #APPLE
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(findstring MINGW,$(UNAME_S)),MINGW)
ifeq ($(OS), Windows_NT)
ECHO_MESSAGE = "MinGW"
LIBS += -lgdi32 -lopengl32 -limm32
ifeq ($(shell pkg-config freeglut --exists 2> /dev/null && echo yes || echo no),yes)

View File

@ -172,7 +172,7 @@
<ClInclude Include="..\..\backends\imgui_impl_opengl2.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\misc\natvis\imgui.natvis" />
<None Include="..\..\misc\debuggers\imgui.natvis" />
<None Include="..\README.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -54,7 +54,7 @@
</ItemGroup>
<ItemGroup>
<None Include="..\README.txt" />
<None Include="..\..\misc\natvis\imgui.natvis">
<None Include="..\..\misc\debuggers\imgui.natvis">
<Filter>sources</Filter>
</None>
</ItemGroup>

View File

@ -2,8 +2,8 @@
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!!
// !!! If someone or something is teaching you GLUT in 2020, you are being abused. Please show some resistance. !!!
// !!! GLUT/FreeGLUT IS OBSOLETE PREHISTORIC SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!!
// !!! If someone or something is teaching you GLUT today, you are being abused. Please show some resistance. !!!
// !!! Nowadays, prefer using GLFW or SDL instead!
#include "imgui.h"
@ -76,7 +76,7 @@ void glut_display_func()
ImGui::Render();
ImGuiIO& io = ImGui::GetIO();
glViewport(0, 0, (GLsizei)io.DisplaySize.x, (GLsizei)io.DisplaySize.y);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound, but prefer using the GL3+ code.
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
@ -111,7 +111,6 @@ int main(int argc, char** argv)
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
// Setup Dear ImGui style
ImGui::StyleColorsDark();

View File

@ -22,7 +22,6 @@ int main(int, char**)
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
// Setup Dear ImGui style
ImGui::StyleColorsDark();

View File

@ -57,11 +57,12 @@ ifeq ($(UNAME_S), Darwin) #APPLE
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(findstring MINGW,$(UNAME_S)),MINGW)
ifeq ($(OS), Windows_NT)
ECHO_MESSAGE = "MinGW"
ifneq ($(WITH_EXTRA_WARNINGS), 0)
CXXFLAGS += -Wextra -Wpedantic
endif
LIBS += -limm32
CFLAGS = $(CXXFLAGS)
endif

View File

@ -1,3 +1,3 @@
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
mkdir Debug
cl /nologo /Zi /MD /I ..\.. %* *.cpp ..\..\*.cpp /FeDebug/example_null.exe /FoDebug/ /link gdi32.lib shell32.lib
cl /nologo /Zi /MD /I ..\.. %* *.cpp ..\..\*.cpp /FeDebug/example_null.exe /FoDebug/ /link gdi32.lib shell32.lib imm32.lib

View File

@ -1,8 +1,8 @@
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
set OUT_DIR=Debug
set OUT_EXE=example_sdl_directx11
set INCLUDES=/I.. /I..\.. /I%SDL2_DIR%\include /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I "%DXSDK_DIR%Include"
set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_dx11.cpp ..\..\imgui*.cpp
set LIBS=/libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d11.lib d3dcompiler.lib
@set OUT_DIR=Debug
@set OUT_EXE=example_sdl_directx11
@set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I "%DXSDK_DIR%Include"
@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_dx11.cpp ..\..\imgui*.cpp
@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d11.lib d3dcompiler.lib
mkdir %OUT_DIR%
cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console

View File

@ -173,7 +173,7 @@
<ClInclude Include="..\..\backends\imgui_impl_sdl.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\misc\natvis\imgui.natvis" />
<None Include="..\..\misc\debuggers\imgui.natvis" />
<None Include="..\README.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -53,7 +53,7 @@
</ItemGroup>
<ItemGroup>
<None Include="..\README.txt" />
<None Include="..\..\misc\natvis\imgui.natvis">
<None Include="..\..\misc\debuggers\imgui.natvis">
<Filter>sources</Filter>
</None>
</ItemGroup>

View File

@ -54,25 +54,13 @@ int main(int, char**)
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigViewportsNoAutoMerge = true;
//io.ConfigViewportsNoTaskBarIcon = true;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
ImGuiStyle& style = ImGui::GetStyle();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
}
// Setup Platform/Renderer backends
ImGui_ImplSDL2_InitForD3D(window);
ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
@ -167,17 +155,11 @@ int main(int, char**)
// Rendering
ImGui::Render();
const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL);
g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, (float*)&clear_color);
g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha);
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
// Update and Render additional Platform Windows
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
}
g_pSwapChain->Present(1, 0); // Present with vsync
//g_pSwapChain->Present(0, 0); // Present without vsync
}

View File

@ -107,7 +107,7 @@ int main(int, char**)
id<CAMetalDrawable> drawable = [layer nextDrawable];
id<MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer];
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0] * clear_color[3], clear_color[1] * clear_color[3], clear_color[2] * clear_color[3], clear_color[3]);
renderPassDescriptor.colorAttachments[0].texture = drawable.texture;
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;

View File

@ -48,7 +48,7 @@ ifeq ($(UNAME_S), Darwin) #APPLE
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(findstring MINGW,$(UNAME_S)),MINGW)
ifeq ($(OS), Windows_NT)
ECHO_MESSAGE = "MinGW"
LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl2`

View File

@ -1,8 +1,8 @@
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
set OUT_DIR=Debug
set OUT_EXE=example_sdl_opengl2
set INCLUDES=/I.. /I..\.. /I%SDL2_DIR%\include
set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_opengl2.cpp ..\..\imgui*.cpp
set LIBS=/libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib
@set OUT_DIR=Debug
@set OUT_EXE=example_sdl_opengl2
@set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include
@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_opengl2.cpp ..\..\imgui*.cpp
@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib
mkdir %OUT_DIR%
cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console

View File

@ -172,7 +172,7 @@
<ClInclude Include="..\..\backends\imgui_impl_sdl.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\misc\natvis\imgui.natvis" />
<None Include="..\..\misc\debuggers\imgui.natvis" />
<None Include="..\README.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -54,7 +54,7 @@
</ItemGroup>
<ItemGroup>
<None Include="..\README.txt" />
<None Include="..\..\misc\natvis\imgui.natvis">
<None Include="..\..\misc\debuggers\imgui.natvis">
<Filter>sources</Filter>
</None>
</ItemGroup>

View File

@ -42,25 +42,13 @@ int main(int, char**)
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigViewportsNoAutoMerge = true;
//io.ConfigViewportsNoTaskBarIcon = true;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
ImGuiStyle& style = ImGui::GetStyle();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
}
// Setup Platform/Renderer backends
ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
ImGui_ImplOpenGL2_Init();
@ -149,23 +137,10 @@ int main(int, char**)
// Rendering
ImGui::Render();
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
// Update and Render additional Platform Windows
// (Platform functions may change the current OpenGL context, so we save/restore it to make it easier to paste this code elsewhere.
// For this specific demo app we could also call SDL_GL_MakeCurrent(window, gl_context) directly)
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
SDL_Window* backup_current_window = SDL_GL_GetCurrentWindow();
SDL_GLContext backup_current_context = SDL_GL_GetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
SDL_GL_MakeCurrent(backup_current_window, backup_current_context);
}
SDL_GL_SwapWindow(window);
}

View File

@ -78,12 +78,12 @@ ifeq ($(UNAME_S), Darwin) #APPLE
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(findstring MINGW,$(UNAME_S)),MINGW)
ECHO_MESSAGE = "MinGW"
LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl2`
ifeq ($(OS), Windows_NT)
ECHO_MESSAGE = "MinGW"
LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl2`
CXXFLAGS += `pkg-config --cflags sdl2`
CFLAGS = $(CXXFLAGS)
CXXFLAGS += `pkg-config --cflags sdl2`
CFLAGS = $(CXXFLAGS)
endif
##---------------------------------------------------------------------

Some files were not shown because too many files have changed in this diff Show More