Compare commits

..

94 Commits
v1.85 ... v1.86

Author SHA1 Message Date
512c54bbc0 Version 1.86 2021-12-22 15:31:13 +01:00
612b787b0d Menus: fixed top-level menu from not consistently using style.PopupRounding. (#4788)
+ Stack tool default size.
2021-12-21 15:05:10 +01:00
4bad852a78 Backends: SDL_Renderer: Handle change to SDL_RenderGeometryRaw() function signature in SDL 2.0.19 (#4819) 2021-12-21 14:32:41 +01:00
0636f9adac InputText: fixed Shift+Delete from not cutting into clipboard. (#4818, #1541) 2021-12-20 19:45:58 +01:00
d9bc1e44af Backends: Marmalade: Removed obsolete Marmalade backend (imgui_impl_marmalade.cpp) + example. (#368, #375) 2021-12-20 19:29:41 +01:00
0cdc4a9565 Backends: Win32: Store left/right variants of Ctrl/Shift/Alt mods in KeysDown[] array. (#2625)
Technically not much required yet but will be by extra-keys work. fix miscleared GLFW field for consistency (no effect)
2021-12-16 18:16:35 +01:00
4a43dcb940 Internals: reduced side-effects of setting window->HiddenFramesForRenderOnly > 0 2021-12-15 16:05:15 +01:00
1c4066cd9e Internals: UpdateWindowInFocusOrderList: amend a528398 to fix docking. (#3496, #4797) 2021-12-15 14:27:56 +01:00
389982eb5a Backends: OpenGL3: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports with some Intel HD drivers.. (#4468, #4504, #2981, #3381) 2021-12-15 11:50:00 +01:00
48f263336b Menus: fixed closing a menu inside a popup/modal. Fixed menu inside a popup/modal not inhibiting hovering of items in the popup/modal. (#3496, #4797)
Fixed sub-menu items inside a popups from closing the popup (debatable).
2021-12-14 16:54:23 +01:00
a528398c77 Internals: support for varying _ChildWindow flag for menu windows. (#3496, #4797) 2021-12-14 16:19:43 +01:00
11638fdf7d Menus: reuse more menu windows when stacked over popups.
This is actually mostly aimed at ensuring the _ChildWindow flag on menu window doesn't vary as this would cause issues with our current g.WindowsFocusOrder[] scheme
2021-12-13 19:35:16 +01:00
0e8c199e87 CI: Use regex to fix vcxproj platform and toolset versions. (#3249) Remove Discord integration. 2021-12-13 14:58:23 +01:00
d7350668d1 Fix OSX warnings + Examples/Apple+GL2 calls super reshape. (#4759, #1873) 2021-12-13 12:31:15 +01:00
1b6b8602c1 Backends: OSX: Fix keyboard support. Handle scroll cancel. Don't set mouse cursor shape unconditionally. (#4759, #4253, #1873)
Note the original FIXME: refered to GLFWs Cocoa implementation, which is largely what this commit provides.
2021-12-13 11:56:43 +01:00
f71ee5203e Fix infinite loop in ImFontGlyphRangesBuilder::AddRanges if the user passes upper range = UINT16_MAX without IMGUI_USE_WCHAR32. (#4802) 2021-12-13 11:35:59 +01:00
b720f1f03c Backends: OSX: Add Game Controller support. (#4759) 2021-12-13 11:25:59 +01:00
8a9fe26866 Menus: fixed closing a menu by clicking on its menu-bar item when inside a popup. (#3496, #4797) 2021-12-10 18:58:41 +01:00
c801799218 Added an assertion for the common user mistake of using "" as an identifier at the root level of a window. (#1414, #2562, #2807, #4008, #4158, #4375, #4548, #4657, #4796)
#4158, #4375, #4548, #4657, #4796)
2021-12-09 15:35:02 +01:00
a8e1dde357 Fix static analyser, update readme. 2021-12-09 15:17:58 +01:00
e03383d088 Fixes for tooltip over modals leading to incorrect modal dimming. (#4729)
Amend 23ef6c1. Should rework tooltip to be in a consistent position in g.Windows[]
2021-12-09 11:50:38 +01:00
bdd2a94315 InputTextMultiline: fixed vertical tracking with large values of FramePadding.y. (#3781, #4794) 2021-12-09 11:30:42 +01:00
072caa4a90 InputText: fixed incorrect padding when FrameBorder > 0. (#4794, #3781) 2021-12-09 11:25:58 +01:00
270d4d0855 Nav, Docking: Fix crash on dimming docked window and DockSpaceOverViewport() with PassthruCentralNode.
(amend 1dc3af3, 23ef6c1, 657073a)

# Conflicts:
#	imgui.cpp
2021-12-08 17:07:07 +01:00
a19815dc6b Backends: Allegro5: Fixed mishandling of the ImDrawCmd::IdxOffset field. (#4790) 2021-12-08 16:34:57 +01:00
c80e8b964c Backends: OpenGL2, Marmalade: Fixed mishandling of the ImDrawCmd::IdxOffset field. (#4790) 2021-12-08 16:26:52 +01:00
b38af0f522 Popups: Fix popups being closed by newly appearing windows. (#4317)
* Popups/modals now remain open when new windows are created from within popup/modal begin stack.
* Modals are not closed when new window appears behind active modal.
Tested by "window_popup_interruptions"
2021-12-07 15:52:13 +01:00
657073a650 Nav, Docking: fix dimming crash with accessing zero-cmd ImDrawList (amend 1dc3af3, 23ef6c1)
# Conflicts:
#	imgui.cpp
2021-12-06 19:16:14 +01:00
20e040c858 Clipper, Tables: remove table specific code path should now be ok (added assert). 2021-12-06 17:17:43 +01:00
926addbfe2 Clipper: fixed invalid state when number of frozen table row is smaller than ItemCount.
+ Bonus rather unorthodox coding style.
2021-12-06 17:17:43 +01:00
027a7ba3eb Clipper: use line size instead of cursor comparaison when range are large. (#3609, #3962 + https://github.com/ocornut/imgui_club/issues/20) 2021-12-06 17:17:43 +01:00
a76bc52da5 Window, Clipper: store initial precision loss and apply in clipper. (#3609, #3962 + https://github.com/ocornut/imgui_club/issues/20) 2021-12-06 16:19:47 +01:00
6e141a9cae Internals: made ScrollbarEx() use ImS64 to facilitate use with larger ranges (not fully tested) + clipper tweaks (#3609, #3962 + https://github.com/ocornut/imgui_club/issues/20)
This does NOT fix all problems with large ranges and floating point precision, it merely attenuate them.
2021-12-06 12:09:38 +01:00
eea836135a InputText: fix buffer modifications in callbacks while using resize callback (#4784)
Regressed by 5ac25e7c7 (#4762)
2021-12-05 19:03:40 +01:00
aa41f16589 Separator: fixed cover all columns while called inside a table. (#4787, #205) 2021-12-05 18:47:28 +01:00
23ef6c149e Reworked modal/ctrl+tab dimming system to be entirely processed at end of the frame (backported 1dc3af3 from docking) 2021-12-03 19:21:39 +01:00
da3a36eefd Backport from docking branch: minor stuff.
Fixed software mouse cursor being rendered multiple times if Render() is called more than once.
2021-12-03 19:11:58 +01:00
78c6435dbb Inputs: (breaking wip) removed IsMouseTripleClicked() added recently (during 1.86 WIP), replaced with GetMouseClickedCount(). (#3229) 2021-12-03 12:38:58 +01:00
5c388c39f4 Backends: SDL_Renderer: Added support for large meshes (64k+ vertices) with 16-bit indices, enable 'ImGuiBackendFlags_RendererHasVtxOffset' in this backend. (#3926) 2021-12-03 12:28:03 +01:00
5b1a70aa2d Fixed RenderRectFilledWithHole() (used by docking) + added dummy EndFrameDrawDimmedBackgrounds() stub in master.
The round corner flag change in 033dfd9d forgot to default to _None.
2021-12-01 15:26:34 +01:00
440824d431 Backends: Fixed early out on empty clip rect. In particular, DX12 backend would warn about it (others not so much). (#4775, #4464)
Amend/fix 2b0bd40b
2021-11-30 21:48:29 +01:00
f087a5b856 Metrics: Added a node showing windows in submission order and showing the Begin() stack. 2021-11-30 16:04:19 +01:00
c5db276521 InputText, Nav: fixed tabbing through InputTextMultiline(). (#4761, #3092)
Messy... Broken by 66f0fb9. Added ImGuiItemFlags_NoTabStop to EndGroup() ahead of time (not strictly needed here).
2021-11-30 15:17:18 +01:00
9d704d99d3 Internals: wrapped ImQsort() in an inline function + added a define guard. 2021-11-30 12:59:00 +01:00
66f0fb986c Inputtext, Nav: fixed using SetKeyboardFocusHere() on InputTextMultiline(). (#4761) 2021-11-29 16:25:45 +01:00
5ccb66794b Backends: WebGPU: Passing explicit buffer sizes as validation layers appears to not do what the in-flux specs says. (#4766 2021-11-29 12:18:25 +01:00
cb5c73f64a Fix: IM_DEBUG_BREAK macro on ARM GCC (#4767) 2021-11-29 00:05:57 +01:00
65f4be1a10 InputText: Internals: moved "apply_new_text" application code to reduce noise in a future commit (will be for #4714) + removed unused fields.
The move would ideally be no-op. technically we now clear state->Flags before calling ResizeCallback but those are unrelated. The 2 unused fields were incorrectly added by 24ff25981.
2021-11-25 15:12:23 +01:00
5ac25e7c7a InputText: fixed ReadOnly flag preventing callbacks from receiving the text buffer. (#4762) 2021-11-25 15:12:08 +01:00
4d9a3b19d5 Internals: Implement a continuable IM_DEBUG_BREAK on GCC for common archs. (#2673) 2021-11-22 12:35:07 +01:00
764f9e606d Fixed crash on right-click without modal, introduced by previous commit a3667f46, (#4729) 2021-11-17 12:45:33 +01:00
a3667f462a Fixed tooltip in own viewport over modal from being incorrectly dimmed. (#4729)
Normally we would aim to ensure that g.Windows[] gets maintained to reflect display layer but it is presently non trivial.
2021-11-16 16:13:04 +01:00
3fde445b91 Misc: Added missing ImGuiMouseCursor_NotAllowed cursor for software rendering (when io.MouseDrawCursor is enabled). (#4713) 2021-11-15 16:19:33 +01:00
d80a9123b7 Internals: move chunks of IsItemHovered() so upcoming commit can be less noisy. This commit should be a no-op (check by comparing without white-space changes) 2021-11-10 20:18:51 +01:00
2c29e391dd Drag and Drop: BeginDragDropSource() with ImGuiDragDropFlags_SourceAllowNullID doesn't lose tooltip when scrolling. (#143)
Reduced amount of self critical commentary since it'll appear like a hack for users but it isn't more a hack than many other things.
2021-11-10 19:17:01 +01:00
f8a806ad9f Tooltips, Internal: (Breaking) swapped parameter order to accomodate for future tooltip api rework. 2021-11-10 17:53:58 +01:00
7cd3cfa58a Demo: Add IMGUI_DEMO_MARKER (currently unused, but usage by altering GImGuiDemoMarkerCallback) (#3689)
Various amends/renames. (Amend to fix a warning)
2021-11-10 13:09:50 +01:00
cad790d43b Nav: fixed backwrap tabbing wrap on sibling child windows with _NavFlattened flag. (#4449)
Amend 1a7526dc
2021-11-10 12:44:43 +01:00
e790fc0e79 Nav: prevent child from clipping items when using _NavFlattened and parent has a pending nav request. (#787) 2021-11-10 12:00:50 +01:00
a9ea1ae854 Nav: fixing assert using Tab in a window without any tabbable element (#4449)
Amend 1a7526dc
2021-11-10 11:42:39 +01:00
eb02dcf87f Nav: enable move/resize window with keyboard in Ctrl+Tabbing windowing menu even without _NavEnableKeyboard. (#4023, #787). 2021-11-08 18:42:07 +01:00
8ce23b3ccd Nav: Ctrl+tabbing to cycle through windows is now enabled regardless of _NavEnableKeyboard. (#4023, #767) 2021-11-08 17:41:36 +01:00
bce1ba400f Clipper: add ForceDisplayRangeByIndices (#3841, #3578)
This partially reverts commit 6a7e2c74fb.
2021-11-08 17:20:30 +01:00
ebac375791 Docs: added info about Freetype, editing sponsors. 2021-11-08 16:22:00 +01:00
1a7526dcd4 Nav, Tabbing: refactor tabbing system to support clipped items, scrolling, using nav queries. (#4449)
Not using counter/modulo anymore and special provisions to handle tab wrapping with ImGuiListClipper. Wrapping may be done better as a next-frame forwarded request.
Also one extra step toward #3949 #3985
2021-11-04 20:48:12 +01:00
f01a6d3e8f InputText, Nav: fixed repeated calls to SetKeyboardFocusHere() preventing to use InputText(). (#4682)
+ Stack Tool: favor inspecting HoveredID over ActiveID as the later is more likely to be locked.
2021-11-04 20:02:42 +01:00
32779c5b64 Clipper: hotfix (amend 93cccd2, was broken) (#3841, #1725) 2021-11-04 15:17:08 +01:00
64daeddf6f Removed CalcListClipping() function. (#3841) 2021-11-04 14:14:16 +01:00
6a7e2c74fb Clipper: remove ForceDisplayRangeByIndices/ForceDisplayRangeByPositions functions until we find a need for them, since #3841 is now solved automatically. 2021-11-04 14:05:14 +01:00
93cccd27f6 Clipper: bunch of rework. (#3841, #1725)
- Focused/NavId now always included in display range.
- Any number of steps (while preserving zero-alloc policy).
- Non contiguous ranges for nav processing
- Moved new fields internally (+ moved StepNo away from sight so it doesn't get missused).
- Generally tweaks/refactors.
2021-11-04 14:05:14 +01:00
cd1b5f7883 Clipper: enhanced ImGuiListClipper (#3841) 2021-11-04 13:56:37 +01:00
b409df34db Clipper: Fixed content height declaration slightly mismatching the one of when not using a clipper. 2021-11-03 17:00:40 +01:00
14466a6d19 Nav: Page/Home/End doesn't immediately restore highlight (before results comes) + pressing Esc to exit a child window re-enable the Nav highlight if it was disabled by mouse.
Also fix a move request fail restoring highlight from not moving mouse cursor.
Add NavRestoreHighlightAfterMove() helper a little bit of extra sanity.
2021-11-02 17:04:35 +01:00
978598b174 Nav: pressing PageUp/PageDown/Home/End when in Menu layer automatically moves back to Main layer. + fixed resizing window from borders setting navigation to Menu layer. 2021-11-02 17:04:34 +01:00
d1eb7b5757 ScrollToItem: amend fully visible tests to take account of spacing used (fix nav in one axis scrolling back and forth between axises when space is tight by just < ItemSpacing*2) (#3692, #2812, #4242, #2900)
Amend 8f495e55
2021-11-02 16:17:12 +01:00
eb654f1bad Typo 2021-11-02 12:57:05 +01:00
b1a68d899c Fix misplaced backtick in FAQ.md (#4669) 2021-11-02 12:51:22 +01:00
a67f7dce31 Nav: relative rectangle positions are now stored relative to CursorStartPos to be independent of scrolling. Will facilitate rework of clipper (#3841)
+ Extracted code into NavUpdateCreateWrappingRequest()
+ Fix for PVS in NavUpdate() assigning g.NavMousePosDirty twice.
2021-10-27 14:18:03 +02:00
8d361c47fb Nav: rework NavEnableSetMousePos application so scrolling is applied more consistently in NavCalcPreferredRefPos() + moved at end of NavUpdate() after the last SetScroll have been done. 2021-10-27 12:55:46 +02:00
8361ed1f54 Nav: wrap abs<>rel rectangle conversions before we attempt to switch the reference point from window->Pos to window->DC.CursorStartPos. This commit should have no effect.
Current point makes rectangle invalid right after a scroll, for interactive actions it's rarely a problem but e.g. clipper will want to use g.NavID rect rel while scrolling. (#3841)
2021-10-27 12:28:45 +02:00
19c72cd52a Nav: fixed absolute mouse position (with NavEnableSetMousePos config flag) when using Home/End leads to scrolling. 2021-10-27 12:28:35 +02:00
c363b6df2b Modals: fixed issue hovering popups inside a child inside a modal. Fixed IsWindowFocused()/IsWindowHovered() issues with childs inside popups. (#4676)(#4676, #4527)
Amend/fix 6b1e094f, fc4988ffb (Sep 24)
2021-10-27 12:03:14 +02:00
0f2898ea88 Demo: Tree selection demo use !IsItemToggledOpen() (#1896) + update FAQ (#4366) 2021-10-25 18:38:56 +02:00
99552420a2 InputText: triple-click avoid scroll + include end of line character. (#2244) 2021-10-25 17:14:00 +02:00
126a6f894f InputText: made double-click select word, triple-line select line. Word delimitation logic differs slightly from the one used by CTRL+arrows. (#2244) 2021-10-25 16:34:56 +02:00
9c78fc928a Inputs: Mouse: Amend c8e3a01 for tracking multiple clicks, renaming. (#3229) 2021-10-25 14:30:20 +02:00
2318c764cf Inputs: Mouse: Add support for tracking multiple clicks more than just double (#3229) 2021-10-25 14:30:17 +02:00
39b99072fb ImVector: fix Clang warning (implicit conversion changes signedness: 'const ptrdiff_t' (aka 'const long long') to 'unsigned long long') 2021-10-22 14:52:26 +02:00
ad3f54ff1a Examples: Emscripten comments (#4650, #4662), standardize readme 2021-10-19 14:17:12 +02:00
19c3773cc0 Backends: Vulkan: Call vkCmdSetScissor() with a full-viewport at end of render. (#4644) 2021-10-15 12:11:11 +02:00
bbd5119a26 Backends: Vulkan: comments about user using VK_DYNAMIC_STATE_VIEWPORT / VK_DYNAMIC_STATE_SCISSOR and not calling vkCmdSetViewport() / vkCmdSetScissor(). (#4644) 2021-10-15 12:01:35 +02:00
e3bd9434b1 1.86 WIP + internals: tweaks table temp data code. 2021-10-14 16:58:14 +02:00
13cdf2ff0e CI: Add MinGW DLL builds, 2021-10-13 17:24:08 +02:00
be03b8ff93 Misc: Fix build with MinGW when using IMGUI_API. 2021-10-12 16:43:28 +02:00
43 changed files with 1910 additions and 1443 deletions

View File

@ -37,20 +37,30 @@ jobs:
- name: Fix Projects
shell: powershell
run: |
# WARNING: This will need updating if toolset/sdk change in project files!
# CI workers do not supporter older Visual Studio versions. Fix projects to target newer available version.
gci -recurse -filter "*.vcxproj" | ForEach-Object {
# Fix SDK and toolset for most samples.
(Get-Content $_.FullName) -Replace "<PlatformToolset>v110</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
# Fix SDK and toolset for samples that require newer SDK/toolset. At the moment it is only dx12.
(Get-Content $_.FullName) -Replace "<PlatformToolset>v140</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
(Get-Content $_.FullName) -Replace "<PlatformToolset>v\d{3}</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>[\d\.]+</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
}
# Not using matrix here because it would inflate job count too much. Check out and setup is done for every job and that makes build times way too long.
- name: Build example_null (extra warnings, mingw 64-bit)
run: mingw32-make -C examples/example_null WITH_EXTRA_WARNINGS=1
- name: Build example_null (mingw 64-bit, as DLL)
shell: bash
run: |
echo '#ifdef _EXPORT' > example_single_file.cpp
echo '# define IMGUI_API __declspec(dllexport)' >> example_single_file.cpp
echo '#else' >> example_single_file.cpp
echo '# define IMGUI_API __declspec(dllimport)' >> example_single_file.cpp
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
g++ -I. -Wall -Wformat -D_EXPORT -shared -o libimgui.dll -Wl,--out-implib,libimgui.a example_single_file.cpp -limm32
g++ -I. -Wall -Wformat -o example_null.exe examples/example_null/main.cpp -L. -limgui
rm -f example_null.exe libimgui.* example_single_file.*
- name: Build example_null (extra warnings, msvc 64-bit)
shell: cmd
run: |
@ -483,34 +493,3 @@ jobs:
run: |
cd examples/example_android_opengl3/android
gradle assembleDebug
Discord-CI:
runs-on: ubuntu-18.04
if: always()
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/g) != null && '{{ run.conclusion }}' != '{{ last_run.conclusion }}'"
discord-username: GitHub Actions
discord-job-new-failure-message: ''
discord-job-fixed-failure-message: ''
discord-job-new-failure-embed: |
{
"title": "`{{ job.name }}` job is failing on `{{ github.branch }}`!",
"description": "Commit [{{ github.context.payload.head_commit.title }}]({{ github.context.payload.head_commit.url }}) pushed to [{{ github.branch }}]({{ github.branch_url }}) broke [{{ job.name }}]({{ job.url }}) build job.\nFailing steps: {{ failing_steps }}",
"url": "{{ job.url }}",
"color": "0xFF0000",
"timestamp": "{{ run.updated_at }}"
}
discord-job-fixed-failure-embed: |
{
"title": "`{{ github.branch }}` branch is no longer failing!",
"description": "Build failures were fixed on [{{ github.branch }}]({{ github.branch_url }}) branch.",
"color": "0x00FF00",
"url": "{{ github.context.payload.head_commit.url }}",
"timestamp": "{{ run.completed_at }}"
}

View File

@ -16,6 +16,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-12-08: Renderer: Fixed mishandling of the the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86.
// 2021-08-17: Calling io.AddFocusEvent() on ALLEGRO_EVENT_DISPLAY_SWITCH_OUT/ALLEGRO_EVENT_DISPLAY_SWITCH_IN events.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-05-19: Renderer: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
@ -155,7 +156,6 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
}
// Render command lists
int idx_offset = 0;
ImVec2 clip_off = draw_data->DisplayPos;
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
@ -174,15 +174,14 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
// Apply scissor/clipping rectangle, Draw
ALLEGRO_BITMAP* texture = (ALLEGRO_BITMAP*)pcmd->GetTexID();
al_set_clipping_rectangle(clip_min.x, clip_min.y, clip_max.x - clip_min.x, clip_max.y - clip_min.y);
al_draw_prim(&vertices[0], bd->VertexDecl, texture, idx_offset, idx_offset + pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST);
al_draw_prim(&vertices[0], bd->VertexDecl, texture, pcmd->IdxOffset, pcmd->IdxOffset + pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST);
}
idx_offset += pcmd->ElemCount;
}
}

View File

@ -256,7 +256,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
// Apply scissor/clipping rectangle

View File

@ -266,7 +266,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
// Apply scissor/clipping rectangle

View File

@ -262,7 +262,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
// Apply Scissor/clipping rectangle, Bind texture, Draw

View File

@ -251,7 +251,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
// Apply Scissor/clipping rectangle, Bind texture, Draw

View File

@ -270,6 +270,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
bd->PrevUserCallbackWindowFocus = NULL;
bd->PrevUserCallbackCursorEnter = NULL;
bd->PrevUserCallbackMousebutton = NULL;
bd->PrevUserCallbackScroll = NULL;
bd->PrevUserCallbackKey = NULL;

View File

@ -1,318 +0,0 @@
// dear imgui: Renderer + Platform Backend for Marmalade + IwGx
// Marmalade code: Copyright (C) 2015 by Giovanni Zito (this file is part of Dear ImGui)
// Implemented features:
// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID!
// Missing features:
// [ ] Renderer: Clipping rectangles are not honored.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// 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-05-19: Renderer: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
// 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter().
// 2018-11-30: Misc: Setting up io.BackendPlatformName/io.BackendRendererName so they can be displayed in the About Window.
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_Marmalade_RenderDrawData() in the .h file so you can call it yourself.
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
#include "imgui.h"
#include "imgui_impl_marmalade.h"
#include <s3eClipboard.h>
#include <s3ePointer.h>
#include <s3eKeyboard.h>
#include <IwTexture.h>
#include <IwGx.h>
// Data
static double g_Time = 0.0f;
static bool g_MousePressed[3] = { false, false, false };
static CIwTexture* g_FontTexture = NULL;
static char* g_ClipboardText = NULL;
static bool g_osdKeyboardEnabled = false;
// use this setting to scale the interface - e.g. on device you could use 2 or 3 scale factor
static ImVec2 g_RenderScale = ImVec2(1.0f, 1.0f);
// Render function.
void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
return;
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
const int nVert = cmd_list->VtxBuffer.Size;
CIwFVec2* pVertStream = IW_GX_ALLOC(CIwFVec2, nVert);
CIwFVec2* pUVStream = IW_GX_ALLOC(CIwFVec2, nVert);
CIwColour* pColStream = IW_GX_ALLOC(CIwColour, nVert);
for (int i = 0; i < nVert; i++)
{
// FIXME-OPT: optimize multiplication on GPU using vertex shader/projection matrix.
pVertStream[i].x = cmd_list->VtxBuffer[i].pos.x * g_RenderScale.x;
pVertStream[i].y = cmd_list->VtxBuffer[i].pos.y * g_RenderScale.y;
pUVStream[i].x = cmd_list->VtxBuffer[i].uv.x;
pUVStream[i].y = cmd_list->VtxBuffer[i].uv.y;
pColStream[i] = cmd_list->VtxBuffer[i].col;
}
IwGxSetVertStreamScreenSpace(pVertStream, nVert);
IwGxSetUVStream(pUVStream);
IwGxSetColStream(pColStream, nVert);
IwGxSetNormStream(0);
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
{
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
// FIXME: Not honoring ClipRect fields.
CIwMaterial* pCurrentMaterial = IW_GX_ALLOC_MATERIAL();
pCurrentMaterial->SetShadeMode(CIwMaterial::SHADE_FLAT);
pCurrentMaterial->SetCullMode(CIwMaterial::CULL_NONE);
pCurrentMaterial->SetFiltering(false);
pCurrentMaterial->SetAlphaMode(CIwMaterial::ALPHA_BLEND);
pCurrentMaterial->SetDepthWriteMode(CIwMaterial::DEPTH_WRITE_NORMAL);
pCurrentMaterial->SetAlphaTestMode(CIwMaterial::ALPHATEST_DISABLED);
pCurrentMaterial->SetTexture((CIwTexture*)pcmd->GetTexID());
IwGxSetMaterial(pCurrentMaterial);
IwGxDrawPrims(IW_GX_TRI_LIST, (uint16*)idx_buffer, pcmd->ElemCount);
}
idx_buffer += pcmd->ElemCount;
}
IwGxFlush();
}
// TODO: restore modified state (i.e. mvp matrix)
}
static const char* ImGui_Marmalade_GetClipboardText(void* /*user_data*/)
{
if (!s3eClipboardAvailable())
return NULL;
if (int size = s3eClipboardGetText(NULL, 0))
{
if (g_ClipboardText)
delete[] g_ClipboardText;
g_ClipboardText = new char[size];
g_ClipboardText[0] = '\0';
s3eClipboardGetText(g_ClipboardText, size);
}
return g_ClipboardText;
}
static void ImGui_Marmalade_SetClipboardText(void* /*user_data*/, const char* text)
{
if (s3eClipboardAvailable())
s3eClipboardSetText(text);
}
int32 ImGui_Marmalade_PointerButtonEventCallback(void* system_data, void* user_data)
{
// pEvent->m_Button is of type s3ePointerButton and indicates which mouse
// button was pressed. For touchscreen this should always have the value
// S3E_POINTER_BUTTON_SELECT
s3ePointerEvent* pEvent = (s3ePointerEvent*)system_data;
if (pEvent->m_Pressed == 1)
{
if (pEvent->m_Button == S3E_POINTER_BUTTON_LEFTMOUSE)
g_MousePressed[0] = true;
if (pEvent->m_Button == S3E_POINTER_BUTTON_RIGHTMOUSE)
g_MousePressed[1] = true;
if (pEvent->m_Button == S3E_POINTER_BUTTON_MIDDLEMOUSE)
g_MousePressed[2] = true;
if (pEvent->m_Button == S3E_POINTER_BUTTON_MOUSEWHEELUP)
io.MouseWheel += pEvent->m_y;
if (pEvent->m_Button == S3E_POINTER_BUTTON_MOUSEWHEELDOWN)
io.MouseWheel += pEvent->m_y;
}
return 0;
}
int32 ImGui_Marmalade_KeyCallback(void* system_data, void* user_data)
{
ImGuiIO& io = ImGui::GetIO();
s3eKeyboardEvent* e = (s3eKeyboardEvent*)system_data;
if (e->m_Pressed == 1)
io.KeysDown[e->m_Key] = true;
if (e->m_Pressed == 0)
io.KeysDown[e->m_Key] = false;
io.KeyCtrl = s3eKeyboardGetState(s3eKeyLeftControl) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightControl) == S3E_KEY_STATE_DOWN;
io.KeyShift = s3eKeyboardGetState(s3eKeyLeftShift) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightShift) == S3E_KEY_STATE_DOWN;
io.KeyAlt = s3eKeyboardGetState(s3eKeyLeftAlt) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightAlt) == S3E_KEY_STATE_DOWN;
io.KeySuper = s3eKeyboardGetState(s3eKeyLeftWindows) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightWindows) == S3E_KEY_STATE_DOWN;
return 0;
}
int32 ImGui_Marmalade_CharCallback(void* system_data, void* user_data)
{
ImGuiIO& io = ImGui::GetIO();
s3eKeyboardCharEvent* e = (s3eKeyboardCharEvent*)system_data;
io.AddInputCharacter((unsigned int)e->m_Char);
return 0;
}
bool ImGui_Marmalade_CreateDeviceObjects()
{
// Build texture atlas
ImGuiIO& io = ImGui::GetIO();
unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
// Upload texture to graphics system
g_FontTexture = new CIwTexture();
g_FontTexture->SetModifiable(true);
CIwImage& image = g_FontTexture->GetImage();
image.SetFormat(CIwImage::ARGB_8888);
image.SetWidth(width);
image.SetHeight(height);
image.SetBuffers(); // allocates and own buffers
image.ReadTexels(pixels);
g_FontTexture->SetMipMapping(false);
g_FontTexture->SetFiltering(false);
g_FontTexture->Upload();
// Store our identifier
io.Fonts->SetTexID((ImTextureID)g_FontTexture);
return true;
}
void ImGui_Marmalade_InvalidateDeviceObjects()
{
if (g_ClipboardText)
{
delete[] g_ClipboardText;
g_ClipboardText = NULL;
}
if (g_FontTexture)
{
ImGui::GetIO().Fonts->SetTexID(0);
delete g_FontTexture;
g_FontTexture = NULL;
}
}
bool ImGui_Marmalade_Init(bool install_callbacks)
{
ImGuiIO& io = ImGui::GetIO();
io.BackendPlatformName = io.BackendRendererName = "imgui_impl_marmalade";
// 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;
io.KeyMap[ImGuiKey_DownArrow] = s3eKeyDown;
io.KeyMap[ImGuiKey_PageUp] = s3eKeyPageUp;
io.KeyMap[ImGuiKey_PageDown] = s3eKeyPageDown;
io.KeyMap[ImGuiKey_Home] = s3eKeyHome;
io.KeyMap[ImGuiKey_End] = s3eKeyEnd;
io.KeyMap[ImGuiKey_Insert] = s3eKeyInsert;
io.KeyMap[ImGuiKey_Delete] = s3eKeyDelete;
io.KeyMap[ImGuiKey_Backspace] = s3eKeyBackspace;
io.KeyMap[ImGuiKey_Space] = s3eKeySpace;
io.KeyMap[ImGuiKey_Enter] = s3eKeyEnter;
io.KeyMap[ImGuiKey_Escape] = s3eKeyEsc;
io.KeyMap[ImGuiKey_KeyPadEnter] = s3eKeyNumPadEnter;
io.KeyMap[ImGuiKey_A] = s3eKeyA;
io.KeyMap[ImGuiKey_C] = s3eKeyC;
io.KeyMap[ImGuiKey_V] = s3eKeyV;
io.KeyMap[ImGuiKey_X] = s3eKeyX;
io.KeyMap[ImGuiKey_Y] = s3eKeyY;
io.KeyMap[ImGuiKey_Z] = s3eKeyZ;
io.SetClipboardTextFn = ImGui_Marmalade_SetClipboardText;
io.GetClipboardTextFn = ImGui_Marmalade_GetClipboardText;
if (install_callbacks)
{
s3ePointerRegister(S3E_POINTER_BUTTON_EVENT, ImGui_Marmalade_PointerButtonEventCallback, 0);
s3eKeyboardRegister(S3E_KEYBOARD_KEY_EVENT, ImGui_Marmalade_KeyCallback, 0);
s3eKeyboardRegister(S3E_KEYBOARD_CHAR_EVENT, ImGui_Marmalade_CharCallback, 0);
}
return true;
}
void ImGui_Marmalade_Shutdown()
{
ImGui_Marmalade_InvalidateDeviceObjects();
}
void ImGui_Marmalade_NewFrame()
{
if (!g_FontTexture)
ImGui_Marmalade_CreateDeviceObjects();
ImGuiIO& io = ImGui::GetIO();
// Setup display size (every frame to accommodate for window resizing)
int w = IwGxGetScreenWidth(), h = IwGxGetScreenHeight();
io.DisplaySize = ImVec2((float)w, (float)h);
// For retina display or other situations where window coordinates are different from framebuffer coordinates. User storage only, presently not used by ImGui.
io.DisplayFramebufferScale = g_scale;
// Setup time step
double current_time = s3eTimerGetUST() / 1000.0f;
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f);
g_Time = current_time;
double mouse_x, mouse_y;
mouse_x = s3ePointerGetX();
mouse_y = s3ePointerGetY();
io.MousePos = ImVec2((float)mouse_x / g_scale.x, (float)mouse_y / g_scale.y); // Mouse position (set to -FLT_MAX,-FLT_MAX if no mouse / on another screen, etc.)
for (int i = 0; i < 3; i++)
{
io.MouseDown[i] = g_MousePressed[i] || s3ePointerGetState((s3ePointerButton)i) != S3E_POINTER_STATE_UP; // 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.
g_MousePressed[i] = false;
}
// TODO: Hide OS mouse cursor if ImGui is drawing it
// s3ePointerSetInt(S3E_POINTER_HIDE_CURSOR,(io.MouseDrawCursor ? 0 : 1));
// Show/hide OSD keyboard
if (io.WantTextInput)
{
// Some text input widget is active?
if (!g_osdKeyboardEnabled)
{
g_osdKeyboardEnabled = true;
s3eKeyboardSetInt(S3E_KEYBOARD_GET_CHAR, 1); // show OSD keyboard
}
}
else
{
// No text input widget is active
if (g_osdKeyboardEnabled)
{
g_osdKeyboardEnabled = false;
s3eKeyboardSetInt(S3E_KEYBOARD_GET_CHAR, 0); // hide OSD keyboard
}
}
}

View File

@ -1,28 +0,0 @@
// dear imgui: Renderer + Platform Backend for Marmalade + IwGx
// Marmalade code: Copyright (C) 2015 by Giovanni Zito (this file is part of Dear ImGui)
// Implemented features:
// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID!
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// 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
IMGUI_IMPL_API bool ImGui_Marmalade_Init(bool install_callbacks);
IMGUI_IMPL_API void ImGui_Marmalade_Shutdown();
IMGUI_IMPL_API void ImGui_Marmalade_NewFrame();
IMGUI_IMPL_API void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data);
// Use if you want to reset your rendering device without losing Dear ImGui state.
IMGUI_IMPL_API void ImGui_Marmalade_InvalidateDeviceObjects();
IMGUI_IMPL_API bool ImGui_Marmalade_CreateDeviceObjects();
// Callbacks (installed by default if you enable 'install_callbacks' during initialization)
// You can also handle inputs yourself and use those as a reference.
IMGUI_IMPL_API int32 ImGui_Marmalade_PointerButtonEventCallback(void* system_data, void* user_data);
IMGUI_IMPL_API int32 ImGui_Marmalade_KeyCallback(void* system_data, void* user_data);
IMGUI_IMPL_API int32 ImGui_Marmalade_CharCallback(void* system_data, void* user_data);

View File

@ -513,7 +513,7 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
// Apply scissor/clipping rectangle

View File

@ -19,6 +19,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-12-08: OpenGL: Fixed mishandling of the the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODEL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications.
@ -203,7 +204,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
// Apply scissor/clipping rectangle (Y is inverted in OpenGL)
@ -211,9 +212,8 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
// Bind texture, Draw
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID());
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer);
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset);
}
idx_buffer += pcmd->ElemCount;
}
}

View File

@ -14,6 +14,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-12-15: OpenGL: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports with some Intel HD drivers.
// 2021-08-23: OpenGL: Fixed ES 3.0 shader ("#version 300 es") use normal precision floats to avoid wobbly rendering at HD resolutions.
// 2021-08-19: OpenGL: Embed and use our own minimal GL loader (imgui_impl_opengl3_loader.h), removing requirement and support for third-party loader.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
@ -174,6 +175,8 @@ struct ImGui_ImplOpenGL3_Data
GLuint AttribLocationVtxUV;
GLuint AttribLocationVtxColor;
unsigned int VboHandle, ElementsHandle;
GLsizeiptr VertexBufferSize;
GLsizeiptr IndexBufferSize;
bool HasClipOrigin;
ImGui_ImplOpenGL3_Data() { memset(this, 0, sizeof(*this)); }
@ -425,8 +428,20 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
const ImDrawList* cmd_list = draw_data->CmdLists[n];
// Upload vertex/index buffers
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert);
GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx);
if (bd->VertexBufferSize < vtx_buffer_size)
{
bd->VertexBufferSize = vtx_buffer_size;
glBufferData(GL_ARRAY_BUFFER, bd->VertexBufferSize, NULL, GL_STREAM_DRAW);
}
if (bd->IndexBufferSize < idx_buffer_size)
{
bd->IndexBufferSize = idx_buffer_size;
glBufferData(GL_ELEMENT_ARRAY_BUFFER, bd->IndexBufferSize, NULL, GL_STREAM_DRAW);
}
glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data);
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
@ -445,7 +460,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
// Apply scissor/clipping rectangle (Y is inverted in OpenGL)

View File

@ -249,11 +249,13 @@ typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer);
GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
#endif
#endif /* GL_VERSION_1_5 */
#ifndef GL_VERSION_2_0
@ -447,6 +449,7 @@ union GL3WProcs {
PFNGLBLENDEQUATIONSEPARATEPROC BlendEquationSeparate;
PFNGLBLENDFUNCSEPARATEPROC BlendFuncSeparate;
PFNGLBUFFERDATAPROC BufferData;
PFNGLBUFFERSUBDATAPROC BufferSubData;
PFNGLCLEARPROC Clear;
PFNGLCLEARCOLORPROC ClearColor;
PFNGLCOMPILESHADERPROC CompileShader;
@ -506,6 +509,7 @@ GL3W_API extern union GL3WProcs imgl3wProcs;
#define glBlendEquationSeparate imgl3wProcs.gl.BlendEquationSeparate
#define glBlendFuncSeparate imgl3wProcs.gl.BlendFuncSeparate
#define glBufferData imgl3wProcs.gl.BufferData
#define glBufferSubData imgl3wProcs.gl.BufferSubData
#define glClear imgl3wProcs.gl.Clear
#define glClearColor imgl3wProcs.gl.ClearColor
#define glCompileShader imgl3wProcs.gl.CompileShader
@ -692,6 +696,7 @@ static const char *proc_names[] = {
"glBlendEquationSeparate",
"glBlendFuncSeparate",
"glBufferData",
"glBufferSubData",
"glClear",
"glClearColor",
"glCompileShader",

View File

@ -5,10 +5,10 @@
// Implemented features:
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [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]..
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Keyboard arrays indexed using kVK_* codes, e.g. ImGui::IsKeyPressed(kVK_Space).
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// 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
@ -18,7 +18,7 @@
@class NSEvent;
@class NSView;
IMGUI_IMPL_API bool ImGui_ImplOSX_Init();
IMGUI_IMPL_API bool ImGui_ImplOSX_Init(NSView* _Nonnull view);
IMGUI_IMPL_API void ImGui_ImplOSX_Shutdown();
IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(NSView* _Nullable view);
IMGUI_IMPL_API bool ImGui_ImplOSX_HandleEvent(NSEvent* _Nonnull event, NSView* _Nullable view);

View File

@ -5,21 +5,25 @@
// Implemented features:
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [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]..
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Keyboard arrays indexed using kVK_* codes, e.g. ImGui::IsKeyPressed(kVK_Space).
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// 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_osx.h"
#import "imgui.h"
#import "imgui_impl_osx.h"
#import <Cocoa/Cocoa.h>
#include <mach/mach_time.h>
#import <mach/mach_time.h>
#import <Carbon/Carbon.h>
#import <GameController/GameController.h>
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-12-13: *BREAKING CHANGE* Add NSView parameter to ImGui_ImplOSX_Init(). Generally fix keyboard support. Using kVK_* codes for keyboard keys.
// 2021-12-13: Add game controller support.
// 2021-09-21: Use mach_absolute_time as CFAbsoluteTimeGetCurrent can jump backwards.
// 2021-08-17: Calling io.AddFocusEvent() on NSApplicationDidBecomeActiveNotification/NSApplicationDidResignActiveNotification events.
// 2021-06-23: Inputs: Added a fix for shortcuts using CTRL key instead of CMD key.
@ -37,15 +41,17 @@
// 2018-07-07: Initial version.
@class ImFocusObserver;
@class KeyEventResponder;
// Data
static double g_HostClockPeriod = 0.0;
static double g_Time = 0.0;
static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};
static bool g_MouseCursorHidden = false;
static bool g_MouseJustPressed[ImGuiMouseButton_COUNT] = {};
static bool g_MouseDown[ImGuiMouseButton_COUNT] = {};
static ImFocusObserver* g_FocusObserver = NULL;
static double g_HostClockPeriod = 0.0;
static double g_Time = 0.0;
static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};
static bool g_MouseCursorHidden = false;
static bool g_MouseJustPressed[ImGuiMouseButton_COUNT] = {};
static bool g_MouseDown[ImGuiMouseButton_COUNT] = {};
static ImFocusObserver* g_FocusObserver = nil;
static KeyEventResponder* g_KeyEventResponder = nil;
// Undocumented methods for creating cursors.
@interface NSCursor()
@ -74,6 +80,102 @@ static void resetKeys()
io.KeyCtrl = io.KeyShift = io.KeyAlt = io.KeySuper = false;
}
/**
KeyEventResponder implements the NSTextInputClient protocol as is required by the macOS text input manager.
The macOS text input manager is invoked by calling the interpretKeyEvents method from the keyDown method.
Keyboard events are then evaluated by the macOS input manager and valid text input is passed back via the
insertText:replacementRange method.
This is the same approach employed by other cross-platform libraries such as SDL2:
https://github.com/spurious/SDL-mirror/blob/e17aacbd09e65a4fd1e166621e011e581fb017a8/src/video/cocoa/SDL_cocoakeyboard.m#L53
and GLFW:
https://github.com/glfw/glfw/blob/b55a517ae0c7b5127dffa79a64f5406021bf9076/src/cocoa_window.m#L722-L723
*/
@interface KeyEventResponder: NSView<NSTextInputClient>
@end
@implementation KeyEventResponder
- (void)viewDidMoveToWindow
{
// Ensure self is a first responder to receive the input events.
[self.window makeFirstResponder:self];
}
- (void)keyDown:(NSEvent*)event
{
// Call to the macOS input manager system.
[self interpretKeyEvents:@[event]];
}
- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange
{
ImGuiIO& io = ImGui::GetIO();
NSString* characters;
if ([aString isKindOfClass:[NSAttributedString class]])
characters = [aString string];
else
characters = (NSString*)aString;
io.AddInputCharactersUTF8(characters.UTF8String);
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
- (void)doCommandBySelector:(SEL)myselector
{
}
- (nullable NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range actualRange:(nullable NSRangePointer)actualRange
{
return nil;
}
- (NSUInteger)characterIndexForPoint:(NSPoint)point
{
return 0;
}
- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(nullable NSRangePointer)actualRange
{
return NSZeroRect;
}
- (BOOL)hasMarkedText
{
return NO;
}
- (NSRange)markedRange
{
return NSMakeRange(NSNotFound, 0);
}
- (NSRange)selectedRange
{
return NSMakeRange(NSNotFound, 0);
}
- (void)setMarkedText:(nonnull id)string selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
{
}
- (void)unmarkText
{
}
- (nonnull NSArray<NSAttributedStringKey>*)validAttributesForMarkedText
{
return @[];
}
@end
@interface ImFocusObserver : NSObject
- (void)onApplicationBecomeActive:(NSNotification*)aNotification;
@ -103,7 +205,7 @@ static void resetKeys()
@end
// Functions
bool ImGui_ImplOSX_Init()
bool ImGui_ImplOSX_Init(NSView* view)
{
ImGuiIO& io = ImGui::GetIO();
@ -115,29 +217,28 @@ bool ImGui_ImplOSX_Init()
io.BackendPlatformName = "imgui_impl_osx";
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeyDown[] array.
const int offset_for_function_keys = 256 - 0xF700;
io.KeyMap[ImGuiKey_Tab] = '\t';
io.KeyMap[ImGuiKey_LeftArrow] = NSLeftArrowFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_RightArrow] = NSRightArrowFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_UpArrow] = NSUpArrowFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_DownArrow] = NSDownArrowFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_PageUp] = NSPageUpFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_PageDown] = NSPageDownFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_Home] = NSHomeFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_End] = NSEndFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_Insert] = NSInsertFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_Delete] = NSDeleteFunctionKey + offset_for_function_keys;
io.KeyMap[ImGuiKey_Backspace] = 127;
io.KeyMap[ImGuiKey_Space] = 32;
io.KeyMap[ImGuiKey_Enter] = 13;
io.KeyMap[ImGuiKey_Escape] = 27;
io.KeyMap[ImGuiKey_KeyPadEnter] = 3;
io.KeyMap[ImGuiKey_A] = 'A';
io.KeyMap[ImGuiKey_C] = 'C';
io.KeyMap[ImGuiKey_V] = 'V';
io.KeyMap[ImGuiKey_X] = 'X';
io.KeyMap[ImGuiKey_Y] = 'Y';
io.KeyMap[ImGuiKey_Z] = 'Z';
io.KeyMap[ImGuiKey_Tab] = kVK_Tab;
io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow;
io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow;
io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow;
io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow;
io.KeyMap[ImGuiKey_PageUp] = kVK_PageUp;
io.KeyMap[ImGuiKey_PageDown] = kVK_PageDown;
io.KeyMap[ImGuiKey_Home] = kVK_Home;
io.KeyMap[ImGuiKey_End] = kVK_End;
io.KeyMap[ImGuiKey_Insert] = kVK_F13;
io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete;
io.KeyMap[ImGuiKey_Backspace] = kVK_Delete;
io.KeyMap[ImGuiKey_Space] = kVK_Space;
io.KeyMap[ImGuiKey_Enter] = kVK_Return;
io.KeyMap[ImGuiKey_Escape] = kVK_Escape;
io.KeyMap[ImGuiKey_KeyPadEnter] = kVK_ANSI_KeypadEnter;
io.KeyMap[ImGuiKey_A] = kVK_ANSI_A;
io.KeyMap[ImGuiKey_C] = kVK_ANSI_C;
io.KeyMap[ImGuiKey_V] = kVK_ANSI_V;
io.KeyMap[ImGuiKey_X] = kVK_ANSI_X;
io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y;
io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z;
// Load cursors. Some of them are undocumented.
g_MouseCursorHidden = false;
@ -190,6 +291,11 @@ bool ImGui_ImplOSX_Init()
name:NSApplicationDidResignActiveNotification
object:nil];
// Add the NSTextInputClient to the view hierarchy,
// to receive keyboard events and translate them to input text.
g_KeyEventResponder = [[KeyEventResponder alloc] initWithFrame:NSZeroRect];
[view addSubview:g_KeyEventResponder];
return true;
}
@ -224,8 +330,12 @@ static void ImGui_ImplOSX_UpdateMouseCursorAndButtons()
}
else
{
// Show OS mouse cursor
[g_MouseCursors[g_MouseCursors[imgui_cursor] ? imgui_cursor : ImGuiMouseCursor_Arrow] set];
NSCursor* desired = g_MouseCursors[imgui_cursor] ?: g_MouseCursors[ImGuiMouseCursor_Arrow];
// -[NSCursor set] generates measureable overhead if called unconditionally.
if (desired != NSCursor.currentCursor)
{
[desired set];
}
if (g_MouseCursorHidden)
{
g_MouseCursorHidden = false;
@ -234,6 +344,50 @@ static void ImGui_ImplOSX_UpdateMouseCursorAndButtons()
}
}
void ImGui_ImplOSX_UpdateGamepads()
{
ImGuiIO& io = ImGui::GetIO();
memset(io.NavInputs, 0, sizeof(io.NavInputs));
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
return;
GCController* controller;
if (@available(macOS 11.0, *))
controller = GCController.current;
else
controller = GCController.controllers.firstObject;
if (controller == nil || controller.extendedGamepad == nil)
{
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
return;
}
GCExtendedGamepad* gp = controller.extendedGamepad;
#define MAP_BUTTON(NAV_NO, NAME) { io.NavInputs[NAV_NO] = gp.NAME.isPressed ? 1.0 : 0.0; }
MAP_BUTTON(ImGuiNavInput_Activate, buttonA);
MAP_BUTTON(ImGuiNavInput_Cancel, buttonB);
MAP_BUTTON(ImGuiNavInput_Menu, buttonX);
MAP_BUTTON(ImGuiNavInput_Input, buttonY);
MAP_BUTTON(ImGuiNavInput_DpadLeft, dpad.left);
MAP_BUTTON(ImGuiNavInput_DpadRight, dpad.right);
MAP_BUTTON(ImGuiNavInput_DpadUp, dpad.up);
MAP_BUTTON(ImGuiNavInput_DpadDown, dpad.down);
MAP_BUTTON(ImGuiNavInput_FocusPrev, leftShoulder);
MAP_BUTTON(ImGuiNavInput_FocusNext, rightShoulder);
MAP_BUTTON(ImGuiNavInput_TweakSlow, leftTrigger);
MAP_BUTTON(ImGuiNavInput_TweakFast, rightTrigger);
#undef MAP_BUTTON
io.NavInputs[ImGuiNavInput_LStickLeft] = gp.leftThumbstick.left.value;
io.NavInputs[ImGuiNavInput_LStickRight] = gp.leftThumbstick.right.value;
io.NavInputs[ImGuiNavInput_LStickUp] = gp.leftThumbstick.up.value;
io.NavInputs[ImGuiNavInput_LStickDown] = gp.leftThumbstick.down.value;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
}
void ImGui_ImplOSX_NewFrame(NSView* view)
{
// Setup display size
@ -256,19 +410,25 @@ void ImGui_ImplOSX_NewFrame(NSView* view)
g_Time = current_time;
ImGui_ImplOSX_UpdateMouseCursorAndButtons();
ImGui_ImplOSX_UpdateGamepads();
}
static int mapCharacterToKey(int c)
NSString* NSStringFromPhase(NSEventPhase phase)
{
if (c >= 'a' && c <= 'z')
return c - 'a' + 'A';
if (c == 25) // SHIFT+TAB -> TAB
return 9;
if (c >= 0 && c < 256)
return c;
if (c >= 0xF700 && c < 0xF700 + 256)
return c - 0xF700 + 256;
return -1;
static NSString* strings[] =
{
@"none",
@"began",
@"stationary",
@"changed",
@"ended",
@"cancelled",
@"mayBegin",
};
int pos = phase == NSEventPhaseNone ? 0 : __builtin_ctzl((NSUInteger)phase) + 1;
return strings[pos];
}
bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
@ -301,6 +461,21 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
if (event.type == NSEventTypeScrollWheel)
{
// Ignore canceled events.
//
// From macOS 12.1, scrolling with two fingers and then decelerating
// by tapping two fingers results in two events appearing:
//
// 1. A scroll wheel NSEvent, with a phase == NSEventPhaseMayBegin, when the user taps
// two fingers to decelerate or stop the scroll events.
//
// 2. A scroll wheel NSEvent, with a phase == NSEventPhaseCancelled, when the user releases the
// two-finger tap. It is this event that sometimes contains large values for scrollingDeltaX and
// scrollingDeltaY. When these are added to the current x and y positions of the scrolling view,
// it appears to jump up or down. It can be observed in Preview, various JetBrains IDEs and here.
if (event.phase == NSEventPhaseCancelled)
return false;
double wheel_dx = 0.0;
double wheel_dy = 0.0;
@ -322,6 +497,8 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
wheel_dy = [event deltaY];
}
//NSLog(@"dx=%0.3ff, dy=%0.3f, phase=%@", wheel_dx, wheel_dy, NSStringFromPhase(event.phase));
if (fabs(wheel_dx) > 0.0)
io.MouseWheelH += (float)wheel_dx * 0.1f;
if (fabs(wheel_dy) > 0.0)
@ -329,57 +506,37 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
return io.WantCaptureMouse;
}
// FIXME: All the key handling is wrong and broken. Refer to GLFW's cocoa_init.mm and cocoa_window.mm.
if (event.type == NSEventTypeKeyDown)
if (event.type == NSEventTypeKeyDown || event.type == NSEventTypeKeyUp)
{
NSString* str = [event characters];
NSUInteger len = [str length];
for (NSUInteger i = 0; i < len; i++)
{
int c = [str characterAtIndex:i];
if (!io.KeySuper && !(c >= 0xF700 && c <= 0xFFFF) && c != 127)
io.AddInputCharacter((unsigned int)c);
// We must reset in case we're pressing a sequence of special keys while keeping the command pressed
int key = mapCharacterToKey(c);
if (key != -1 && key < 256 && !io.KeySuper)
resetKeys();
if (key != -1)
io.KeysDown[key] = true;
}
return io.WantCaptureKeyboard;
}
if (event.type == NSEventTypeKeyUp)
{
NSString* str = [event characters];
NSUInteger len = [str length];
for (NSUInteger i = 0; i < len; i++)
{
int c = [str characterAtIndex:i];
int key = mapCharacterToKey(c);
if (key != -1)
io.KeysDown[key] = false;
}
unsigned short code = event.keyCode;
IM_ASSERT(code >= 0 && code < IM_ARRAYSIZE(io.KeysDown));
io.KeysDown[code] = event.type == NSEventTypeKeyDown;
NSEventModifierFlags flags = event.modifierFlags;
io.KeyCtrl = (flags & NSEventModifierFlagControl) != 0;
io.KeyShift = (flags & NSEventModifierFlagShift) != 0;
io.KeyAlt = (flags & NSEventModifierFlagOption) != 0;
io.KeySuper = (flags & NSEventModifierFlagCommand) != 0;
return io.WantCaptureKeyboard;
}
if (event.type == NSEventTypeFlagsChanged)
{
unsigned int flags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
bool oldKeyCtrl = io.KeyCtrl;
bool oldKeyShift = io.KeyShift;
bool oldKeyAlt = io.KeyAlt;
bool oldKeySuper = io.KeySuper;
io.KeyCtrl = flags & NSEventModifierFlagControl;
io.KeyShift = flags & NSEventModifierFlagShift;
io.KeyAlt = flags & NSEventModifierFlagOption;
io.KeySuper = flags & NSEventModifierFlagCommand;
// We must reset them as we will not receive any keyUp event if they where pressed with a modifier
if ((oldKeyShift && !io.KeyShift) || (oldKeyCtrl && !io.KeyCtrl) || (oldKeyAlt && !io.KeyAlt) || (oldKeySuper && !io.KeySuper))
resetKeys();
NSEventModifierFlags flags = event.modifierFlags;
switch (event.keyCode)
{
case kVK_Control:
io.KeyCtrl = (flags & NSEventModifierFlagControl) != 0;
break;
case kVK_Shift:
io.KeyShift = (flags & NSEventModifierFlagShift) != 0;
break;
case kVK_Option:
io.KeyAlt = (flags & NSEventModifierFlagOption) != 0;
break;
case kVK_Command:
io.KeySuper = (flags & NSEventModifierFlagCommand) != 0;
break;
}
return io.WantCaptureKeyboard;
}

View File

@ -1,20 +1,25 @@
// dear imgui: Renderer Backend for SDL_Renderer
// (Requires: SDL 2.0.17+)
// Important to understand: SDL_Renderer is an _optional_ component of SDL. We do not recommend you use SDL_Renderer
// because it provide a rather limited API to the end-user. We provide this backend for the sake of completeness.
// Important to understand: SDL_Renderer is an _optional_ component of SDL.
// For a multi-platform app consider using e.g. SDL+DirectX on Windows and SDL+OpenGL on Linux/OSX.
// If your application will want to render any non trivial amount of graphics other than UI,
// please be aware that SDL_Renderer offers a limited graphic API to the end-user and it might
// be difficult to step out of those boundaries.
// However, we understand it is a convenient choice to get an app started easily.
// Implemented features:
// [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// Missing features:
// [ ] 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
// 2021-12-21: Update SDL_RenderGeometryRaw() format to work with SDL 2.0.19.
// 2021-12-03: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2021-10-06: Backup and restore modified ClipRect/Viewport.
// 2021-09-21: Initial version.
@ -58,6 +63,7 @@ bool ImGui_ImplSDLRenderer_Init(SDL_Renderer* renderer)
ImGui_ImplSDLRenderer_Data* bd = IM_NEW(ImGui_ImplSDLRenderer_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_sdlrenderer";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
bd->SDLRenderer = renderer;
@ -124,7 +130,7 @@ void ImGui_ImplSDLRenderer_RenderDrawData(ImDrawData* draw_data)
SDL_Rect ClipRect;
};
BackupSDLRendererState old = {};
old.ClipEnabled = SDL_RenderIsClipEnabled(bd->SDLRenderer);
old.ClipEnabled = SDL_RenderIsClipEnabled(bd->SDLRenderer) == SDL_TRUE;
SDL_RenderGetViewport(bd->SDLRenderer, &old.Viewport);
SDL_RenderGetClipRect(bd->SDLRenderer, &old.ClipRect);
@ -161,15 +167,19 @@ void ImGui_ImplSDLRenderer_RenderDrawData(ImDrawData* draw_data)
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
SDL_Rect r = { (int)(clip_min.x), (int)(clip_min.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y) };
SDL_RenderSetClipRect(bd->SDLRenderer, &r);
const float* xy = (const float*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, pos));
const float* uv = (const float*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv));
const int* color = (const int*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col));
const float* xy = (const float*)((const char*)(vtx_buffer + pcmd->VtxOffset) + IM_OFFSETOF(ImDrawVert, pos));
const float* uv = (const float*)((const char*)(vtx_buffer + pcmd->VtxOffset) + IM_OFFSETOF(ImDrawVert, uv));
#if SDL_VERSION_ATLEAST(2,0,19)
const SDL_Color* color = (const SDL_Color*)((const char*)(vtx_buffer + pcmd->VtxOffset) + IM_OFFSETOF(ImDrawVert, col)); // SDL 2.0.19+
#else
const int* color = (const int*)((const char*)(vtx_buffer + pcmd->VtxOffset) + IM_OFFSETOF(ImDrawVert, col)); // SDL 2.0.17 and 2.0.18
#endif
// Bind texture, Draw
SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID();
@ -177,7 +187,7 @@ void ImGui_ImplSDLRenderer_RenderDrawData(ImDrawData* draw_data)
xy, (int)sizeof(ImDrawVert),
color, (int)sizeof(ImDrawVert),
uv, (int)sizeof(ImDrawVert),
cmd_list->VtxBuffer.Size,
cmd_list->VtxBuffer.Size - pcmd->VtxOffset,
idx_buffer + pcmd->IdxOffset, pcmd->ElemCount, sizeof(ImDrawIdx));
}
}

View File

@ -1,14 +1,16 @@
// dear imgui: Renderer Backend for SDL_Renderer
// (Requires: SDL 2.0.17+)
// Important to understand: SDL_Renderer is an _optional_ component of SDL. We do not recommend you use SDL_Renderer
// because it provide a rather limited API to the end-user. We provide this backend for the sake of completeness.
// Important to understand: SDL_Renderer is an _optional_ component of SDL.
// For a multi-platform app consider using e.g. SDL+DirectX on Windows and SDL+OpenGL on Linux/OSX.
// If your application will want to render any non trivial amount of graphics other than UI,
// please be aware that SDL_Renderer offers a limited graphic API to the end-user and it might
// be difficult to step out of those boundaries.
// However, we understand it is a convenient choice to get an app started easily.
// Implemented features:
// [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID!
// Missing features:
// [ ] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
#pragma once
#include "imgui.h" // IMGUI_IMPL_API

View File

@ -23,6 +23,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-10-15: Vulkan: Call vkCmdSetScissor() at the end of render a full-viewport to reduce likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling vkCmdSetScissor() explicitly every frame.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-03-22: Vulkan: Fix mapped memory validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize.
// 2021-02-18: Vulkan: Change blending equation to preserve alpha in output buffer.
@ -519,7 +520,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
// Apply scissor/clipping rectangle
@ -537,6 +538,16 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
global_idx_offset += cmd_list->IdxBuffer.Size;
global_vtx_offset += cmd_list->VtxBuffer.Size;
}
// Note: at this point both vkCmdSetViewport() and vkCmdSetScissor() have been called.
// Our last values will leak into user/application rendering IF:
// - Your app uses a pipeline with VK_DYNAMIC_STATE_VIEWPORT or VK_DYNAMIC_STATE_SCISSOR dynamic state
// - And you forgot to call vkCmdSetViewport() and vkCmdSetScissor() yourself to explicitely set that state.
// If you use VK_DYNAMIC_STATE_VIEWPORT or VK_DYNAMIC_STATE_SCISSOR you are responsible for setting the values before rendering.
// In theory we should aim to backup/restore those values but I am not sure this is possible.
// We perform a call to vkCmdSetScissor() to set back a full viewport which is likely to fix things for 99% users but technically this is not perfect. (See github #4644)
VkRect2D scissor = { { 0, 0 }, { (uint32_t)fb_width, (uint32_t)fb_height } };
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
}
bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)

View File

@ -13,6 +13,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-11-29: Passing explicit buffer sizes to wgpuRenderPassEncoderSetVertexBuffer()/wgpuRenderPassEncoderSetIndexBuffer().
// 2021-08-24: Fix for latest specs.
// 2021-05-24: Add support for draw_data->FramebufferScale.
// 2021-05-19: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
@ -313,8 +314,8 @@ static void ImGui_ImplWGPU_SetupRenderState(ImDrawData* draw_data, WGPURenderPas
wgpuRenderPassEncoderSetViewport(ctx, 0, 0, draw_data->FramebufferScale.x * draw_data->DisplaySize.x, draw_data->FramebufferScale.y * draw_data->DisplaySize.y, 0, 1);
// Bind shader and vertex buffers
wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, 0, 0);
wgpuRenderPassEncoderSetIndexBuffer(ctx, fr->IndexBuffer, sizeof(ImDrawIdx) == 2 ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32, 0, 0);
wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, 0, fr->VertexBufferSize);
wgpuRenderPassEncoderSetIndexBuffer(ctx, fr->IndexBuffer, sizeof(ImDrawIdx) == 2 ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32, 0, fr->IndexBufferSize);
wgpuRenderPassEncoderSetPipeline(ctx, g_pipelineState);
wgpuRenderPassEncoderSetBindGroup(ctx, 0, g_resources.CommonBindGroup, 0, NULL);
@ -446,7 +447,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
// Apply scissor/clipping rectangle, Draw

View File

@ -33,8 +33,9 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-12-16: Inputs: Fill VK_LCONTROL/VK_RCONTROL/VK_LSHIFT/VK_RSHIFT/VK_LMENU/VK_RMENU for completeness.
// 2021-08-17: Calling io.AddFocusEvent() on WM_SETFOCUS/WM_KILLFOCUS messages.
// 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host windo doesn't have focus.
// 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host window doesn't have focus.
// 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using TrackMouseEvent() to receive WM_MOUSELEAVE events).
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-06-08: Fixed ImGui_ImplWin32_EnableDpiAwareness() and ImGui_ImplWin32_GetDpiScaleForMonitor() to handle Windows 8.1/10 features without a manifest (per-monitor DPI, and properly calls SetProcessDpiAwareness() on 8.1).
@ -426,11 +427,23 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
if (wParam < 256)
io.KeysDown[wParam] = down;
if (wParam == VK_CONTROL)
io.KeyCtrl = down;
{
io.KeysDown[VK_LCONTROL] = ((::GetKeyState(VK_LCONTROL) & 0x8000) != 0);
io.KeysDown[VK_RCONTROL] = ((::GetKeyState(VK_RCONTROL) & 0x8000) != 0);
io.KeyCtrl = io.KeysDown[VK_LCONTROL] || io.KeysDown[VK_RCONTROL];
}
if (wParam == VK_SHIFT)
io.KeyShift = down;
{
io.KeysDown[VK_LSHIFT] = ((::GetKeyState(VK_LSHIFT) & 0x8000) != 0);
io.KeysDown[VK_RSHIFT] = ((::GetKeyState(VK_RSHIFT) & 0x8000) != 0);
io.KeyShift = io.KeysDown[VK_LSHIFT] || io.KeysDown[VK_RSHIFT];
}
if (wParam == VK_MENU)
io.KeyAlt = down;
{
io.KeysDown[VK_LMENU] = ((::GetKeyState(VK_LMENU) & 0x8000) != 0);
io.KeysDown[VK_RMENU] = ((::GetKeyState(VK_RMENU) & 0x8000) != 0);
io.KeyAlt = io.KeysDown[VK_LMENU] || io.KeysDown[VK_RMENU];
}
return 0;
}
case WM_SETFOCUS:

View File

@ -12,7 +12,7 @@ your application or engine to easily integrate Dear ImGui.** Each backend is typ
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.
e.g. Allegro 5 ([imgui_impl_allegro5.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_allegro5.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. 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.
@ -82,14 +82,13 @@ List of Renderer Backends:
List of high-level Frameworks Backends (combining Platform + Renderer):
imgui_impl_allegro5.cpp
imgui_impl_marmalade.cpp
Emscripten is also supported.
The [example_emscripten_opengl3](https://github.com/ocornut/imgui/tree/master/examples/example_emscripten_opengl3) app uses imgui_impl_sdl.cpp + imgui_impl_opengl3.cpp, but other combos are possible.
### Backends for third-party frameworks, graphics API or other languages
See https://github.com/ocornut/imgui/wiki/Bindings for the full list.
See https://github.com/ocornut/imgui/wiki/Bindings for the full list (e.g. Adventure Game Studio, Cinder, Cocos2d-x, Game Maker Studio2, Godot, L<EFBFBD>VE+LUA, Magnum, Monogame, Ogre, openFrameworks, OpenSceneGraph, SFML, Sokol, Unity, Unreal Engine and many others).
### Recommended Backends
@ -128,7 +127,10 @@ Once it works, if you really need it you can replace parts of backends with your
and you have high-level systems everywhere.<BR>
Suggestion: try using a non-portable backend first (e.g. win32 + underlying graphics API) to get
your desktop builds working first. This will get you running faster and get your acquainted with
how Dear ImGui works and is setup. You can then rewrite a custom backend using your own engine API.
how Dear ImGui works and is setup. You can then rewrite a custom backend using your own engine API...
Generally:
It is unlikely you will add value to your project by creating your own backend.
Also:
The [multi-viewports feature](https://github.com/ocornut/imgui/issues/1542) of the 'docking' branch allows

View File

@ -30,6 +30,102 @@ HOW TO UPDATE?
and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users.
- Please report any issue!
-----------------------------------------------------------------------
VERSION 1.86 (Released 2021-12-22)
-----------------------------------------------------------------------
Breaking Changes:
- Removed CalcListClipping() function. Prefer using ImGuiListClipper which can return non-contiguous ranges.
Please open an issue if you think you really need this function. (#3841)
- Backends: OSX: Added NSView* parameter to ImGui_ImplOSX_Init(). (#4759) [@stuartcarnie]
- Backends: Marmalade: Removed obsolete Marmalade backend (imgui_impl_marmalade.cpp) + example app. (#368, #375)
Find last supported version at https://github.com/ocornut/imgui/wiki/Bindings
Other Changes:
- Added an assertion for the common user mistake of using "" as an identifier at the root level of a window
instead of using "##something". Empty identifiers are valid and useful in a very small amount of cases,
but 99.9% of the time if you need an empty label you should use "##something". (#1414, #2562, #2807, #4008,
#4158, #4375, #4548, #4657, #4796). READ THE FAQ ABOUT HOW THE ID STACK WORKS -> https://dearimgui.org/faq
- Added GetMouseClickedCount() function, returning the number of successive clicks. (#3229) [@kudaba]
(so IsMouseDoubleClicked(ImGuiMouseButton_Left) is same as GetMouseClickedCount(ImGuiMouseButton_Left) == 2,
but it allows testing for triple clicks and more).
- Modals: fixed issue hovering popups inside a child windows inside a modal. (#4676, #4527)
- Modals, Popups, Windows: changes how appearing windows are interrupting popups and modals. (#4317) [@rokups]
- appearing windows created from within the begin stack of a popup/modal will no longer close it.
- appearing windows created not within the begin stack of a modal will no longer close the modal,
and automatically appear behind it.
- Fixed IsWindowFocused()/IsWindowHovered() issues with child windows inside popups. (#4676)
- Nav: Ctrl+tabbing to cycle through windows is now enabled regardless of using the _NavEnableKeyboard
configuration flag. This is part of an effort to generalize the use of keyboard inputs. (#4023, #787).
Note that while this is active you can also moving windows (with arrow) and resize (shift+arrows).
- Nav: tabbing now cycles through clipped items and scroll accordingly. (#4449)
- Nav: pressing PageUp/PageDown/Home/End when in Menu layer automatically moves back to Main layer.
- Nav: fixed resizing window from borders setting navigation to Menu layer.
- Nav: prevent child from clipping items when using _NavFlattened and parent has a pending request.
- Nav: pressing Esc to exit a child window reactivates the Nav highlight if it was disabled by mouse.
- Nav: with ImGuiConfigFlags_NavEnableSetMousePos enabled: Fixed absolute mouse position when using
Home/End leads to scrolling. Fixed not setting mouse position when a failed move request (e.g. when
already at edge) reactivates the navigation highlight.
- Menus: fixed closing a menu inside a popup/modal by clicking on the popup/modal. (#3496, #4797)
- Menus: fixed closing a menu by clicking on its menu-bar item when inside a popup. (#3496, #4797) [@xndcn]
- Menus: fixed menu inside a popup/modal not inhibiting hovering of items in the popup/modal. (#3496, #4797)
- Menus: fixed sub-menu items inside a popups from closing the popup.
- Menus: fixed top-level menu from not consistently using style.PopupRounding. (#4788)
- InputText, Nav: fixed repeated calls to SetKeyboardFocusHere() preventing to use InputText(). (#4682)
- Inputtext, Nav: fixed using SetKeyboardFocusHere() on InputTextMultiline(). (#4761)
- InputText: made double-click select word, triple-line select line. Word delimitation logic differs
slightly from the one used by CTRL+arrows. (#2244)
- InputText: fixed ReadOnly flag preventing callbacks from receiving the text buffer. (#4762) [@actondev]
- InputText: fixed Shift+Delete from not cutting into clipboard. (#4818, #1541) [@corporateshark]
- InputTextMultiline: fixed incorrect padding when FrameBorder > 0. (#3781, #4794)
- InputTextMultiline: fixed vertical tracking with large values of FramePadding.y. (#3781, #4794)
- Separator: fixed cover all columns while called inside a table. (#4787)
- Clipper: currently focused item is automatically included in clipper range.
Fixes issue where e.g. drag and dropping an item and scrolling ensure the item source location is
still submitted. (#3841, #1725) [@GamingMinds-DanielC, @ocornut]
- Clipper: added ForceDisplayRangeByIndices() to force a given item (or several) to be stepped out
during a clipping operation. (#3841) [@@GamingMinds-DanielC]
- Clipper: rework so gamepad/keyboard navigation doesn't create spikes in number of items requested
by the clipper to display. (#3841)
- Clipper: fixed content height declaration slightly mismatching the value of when not using a clipper.
(an additional ItemSpacing.y was declared, affecting scrollbar range).
- Clipper: various and incomplete changes to tame down scrolling and precision issues on very large ranges.
Passing an explicit height to the clipper now allows larger ranges. (#3609, #3962).
- Clipper: fixed invalid state when number of frozen table row is smaller than ItemCount.
- Drag and Drop: BeginDragDropSource() with ImGuiDragDropFlags_SourceAllowNullID doesn't lose
tooltip when scrolling. (#143)
- Fonts: fixed infinite loop in ImFontGlyphRangesBuilder::AddRanges() when passing UINT16_MAX or UINT32_MAX
without the IMGUI_USE_WCHAR32 compile-time option. (#4802) [@SlavicPotato]
- Metrics: Added a node showing windows in submission order and showing the Begin() stack.
- Misc: Added missing ImGuiMouseCursor_NotAllowed cursor for software rendering (when the
io.MouseDrawCursor flag is enabled). (#4713) [@nobody-special666]
- Misc: Fixed software mouse cursor being rendered multiple times if Render() is called more than once.
- Misc: Fix MinGW DLL build issue (when IMGUI_API is defined). [@rokups]
- CI: Add MinGW DLL build to test suite. [@rokups]
- Backends: Vulkan: Call vkCmdSetScissor() at the end of render with a full-viewport to reduce
likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling
vkCmdSetScissor() explicitly every frame. (#4644)
- Backends: OpenGL3: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports
with some Intel HD drivers, and perhaps improve performances. (#4468, #4504, #2981, #3381) [@parbo]
- Backends: OpenGL2, Allegro5, Marmalade: Fixed mishandling of the ImDrawCmd::IdxOffset field.
This is an old bug, but due to the way we created drawlists, it never had any visible side-effect before.
The new code for handling Modal and CTRL+Tab dimming/whitening recently made the bug surface. (#4790)
- Backends: Win32: Store left/right variants of Ctrl/Shift/Alt mods in KeysDown[] array. (#2625) [@thedmd]
- Backends: DX12: Fixed DRAW_EMPTY_SCISSOR_RECTANGLE warnings. (#4775)
- Backends: SDL_Renderer: Added support for large meshes (64k+ vertices) with 16-bit indices,
enabling 'ImGuiBackendFlags_RendererHasVtxOffset' in the backend. (#3926) [@rokups]
- Backends: SDL_Renderer: Fix for SDL 2.0.19+ RenderGeometryRaw() API signature change. (#4819) [@sridenour]
- Backends: OSX: Generally fix keyboard support. Keyboard arrays indexed using kVK_* codes, e.g.
ImGui::IsKeyPressed(kVK_Space). Don't set mouse cursor shape unconditionally. Handle two fingers scroll
cancel event. (#4759, #4253, #1873) [@stuartcarnie]
- Backends: OSX: Add Game Controller support (need linking GameController framework) (#4759) [@stuartcarnie]
- Backends: WebGPU: Passing explicit buffer sizes to wgpuRenderPassEncoderSetVertexBuffer() and
wgpuRenderPassEncoderSetIndexBuffer() functions as validation layers appears to not do what the
in-flux specs says. (#4766) [@meshula]
-----------------------------------------------------------------------
VERSION 1.85 (Released 2021-10-12)
-----------------------------------------------------------------------

View File

@ -141,10 +141,6 @@ GLUT (e.g., FreeGLUT on Linux/Windows, GLUT framework on OSX) + OpenGL2 example.
= main.cpp + imgui_impl_glut.cpp + imgui_impl_opengl2.cpp <BR>
Note that GLUT/FreeGLUT is largely obsolete software, prefer using GLFW or SDL.
[example_marmalade/](https://github.com/ocornut/imgui/blob/master/examples/example_marmalade/) <BR>
Marmalade example using IwGx. <BR>
= main.cpp + imgui_impl_marmalade.cpp
[example_null/](https://github.com/ocornut/imgui/blob/master/examples/example_null/) <BR>
Null example, compile and link imgui, create context, run headless with no inputs and no graphics output. <BR>
= main.cpp <BR>

View File

@ -23,7 +23,7 @@ or view this file with any Markdown viewer.
| [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) |
| [I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-displaying-outside-their-expected-windows-boundaries) |
| **Q&A: Usage** |
| **[About the ID Stack system..<br>Why is my widget not reacting when I click on it?<br>How can I have widgets with an empty label?<br>How can I have multiple widgets with the same label?](#q-about-the-id-stack-system)** |
| **[About the ID Stack system..<br>Why is my widget not reacting when I click on it?<br>How can I have widgets with an empty label?<br>How can I have multiple widgets with the same label?<br>How can I have multiple windows with the same label?](#q-about-the-id-stack-system)** |
| [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) |
@ -190,6 +190,7 @@ Refer to rendering backends in the [examples/](https://github.com/ocornut/imgui/
### Q: Why is my widget not reacting when I click on it?
### Q: How can I have widgets with an empty label?
### Q: How can I have multiple widgets with the same label?
### Q: How can I have multiple windows with the same label?
A primer on labels and the ID Stack...
@ -474,7 +475,7 @@ ImGui::End();
- 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 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)

View File

@ -118,7 +118,7 @@ Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/
Officially maintained backends/bindings (in repository):
- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_Renderer, Vulkan, WebGPU.
- Platforms: GLFW, SDL2, Win32, Glut, OSX, Android.
- Frameworks: Emscripten, Allegro5, Marmalade.
- Frameworks: Allegro5, Emscripten.
[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, Lobster, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift...
@ -201,13 +201,13 @@ Ongoing Dear ImGui development is currently financially supported by users and p
- [Blizzard](https://careers.blizzard.com/en-us/openings/engineering/all/all/all/1)
*Double-chocolate sponsors*
- [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)
- [Ubisoft](https://montreal.ubisoft.com/en/ubisoft-sponsors-user-interface-library-for-c-dear-imgui), [Supercell](https://supercell.com)
*Chocolate sponsors*
- [Activision](https://careers.activision.com/c/programmingsoftware-engineering-jobs), [Adobe](https://www.adobe.com/products/medium.html), [Aras Pranckevičius](https://aras-p.info), [Arkane Studios](https://www.arkane-studios.com), [Epic](https://www.unrealengine.com/en-US/megagrants), [RAD Game Tools](http://www.radgametools.com/)
- [Activision](https://careers.activision.com/c/programmingsoftware-engineering-jobs), [Adobe](https://www.adobe.com/products/medium.html), [Aras Pranckevičius](https://aras-p.info), [Arkane Studios](https://www.arkane-studios.com), [Epic](https://www.unrealengine.com/en-US/megagrants), [Google](https://github.com/google/filament), [Nvidia](https://developer.nvidia.com/nvidia-omniverse), [RAD Game Tools](http://www.radgametools.com/)
*Salty-caramel sponsors*
- [Framefield](http://framefield.com), [Grinding Gear Games](https://www.grindinggear.com), [Kylotonn](https://www.kylotonn.com), [Next Level Games](https://www.nextlevelgames.com), [O-Net Communications (USA)](http://en.o-netcom.com), [Supercell](https://supercell.com).
- [Framefield](http://framefield.com), [Grinding Gear Games](https://www.grindinggear.com), [Kylotonn](https://www.kylotonn.com), [Next Level Games](https://www.nextlevelgames.com), [O-Net Communications (USA)](http://en.o-netcom.com)
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.

View File

@ -142,7 +142,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- plot: option/feature: draw unit
- plot: add a helper e.g. Plot(char* label, float value, float time_span=2.0f) that stores values and Plot them for you - probably another function name. and/or automatically allow to plot ANY displayed value (more reliance on stable ID)
- clipper: ability to force display 1 item in the list would be convenient (for patterns where we need to set active id etc.)
- clipper: ability to disable the clipping through a simple flag/bool.
- clipper: ability to run without knowing full count in advance.
- clipper: horizontal clipping support. (#2580)
@ -341,7 +340,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- nav: NavFlattened: broken: in typical usage scenario, the items of a fully clipped child are currently not considered to enter into a NavFlattened child.
- nav: NavFlattened: cannot access menu-bar of a flattened child window with Alt/menu key (not a very common use case..).
- nav: simulate right-click or context activation? (SHIFT+F10)
- nav/tabbing: refactor old tabbing system and turn into navigation, should pass through all widgets (in submission order?).
- nav/popup: esc/enter default behavior for popups, e.g. be able to mark an "ok" or "cancel" button that would get triggered by those keys, default validation button, etc.
- nav/treenode: left within a tree node block as a fallback (ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default?)
- nav/menus: pressing left-right on a vertically clipped menu bar tends to jump to the collapse/close buttons.

View File

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
05318E0F274C397200A8DE2E /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05318E0E274C397200A8DE2E /* GameController.framework */; };
07A82ED82139413D0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; };
07A82ED92139418F0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; };
5079822E257677DB0038A28D /* imgui_tables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5079822D257677DB0038A28D /* imgui_tables.cpp */; };
@ -32,6 +33,7 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
05318E0E274C397200A8DE2E /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
07A82ED62139413C0078D120 /* imgui_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_internal.h; path = ../../imgui_internal.h; sourceTree = "<group>"; };
07A82ED72139413C0078D120 /* imgui_widgets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_widgets.cpp; path = ../../imgui_widgets.cpp; sourceTree = "<group>"; };
5079822D257677DB0038A28D /* imgui_tables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_tables.cpp; path = ../../imgui_tables.cpp; sourceTree = "<group>"; };
@ -76,6 +78,7 @@
files = (
8309BDC6253CCCFE0045E2A1 /* AppKit.framework in Frameworks */,
83BBE9EC20EB471700295997 /* MetalKit.framework in Frameworks */,
05318E0F274C397200A8DE2E /* GameController.framework in Frameworks */,
83BBE9ED20EB471700295997 /* Metal.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -133,6 +136,7 @@
83BBE9E320EB46B800295997 /* Frameworks */ = {
isa = PBXGroup;
children = (
05318E0E274C397200A8DE2E /* GameController.framework */,
8309BDC5253CCCFE0045E2A1 /* AppKit.framework */,
8309BD8E253CCAAA0045E2A1 /* UIKit.framework */,
83BBE9EE20EB471C00295997 /* ModelIO.framework */,

View File

@ -119,7 +119,7 @@
return event;
}];
ImGui_ImplOSX_Init();
ImGui_ImplOSX_Init(self.view);
#endif
}

View File

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
05E31B59274EF0700083FCB6 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05E31B57274EF0360083FCB6 /* GameController.framework */; };
07A82EDB213941D00078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82EDA213941D00078D120 /* imgui_widgets.cpp */; };
4080A99820B02D340036BA46 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4080A98A20B02CD90036BA46 /* main.mm */; };
4080A9A220B034280036BA46 /* imgui_impl_opengl2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4080A99E20B034280036BA46 /* imgui_impl_opengl2.cpp */; };
@ -32,6 +33,7 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
05E31B57274EF0360083FCB6 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
07A82EDA213941D00078D120 /* imgui_widgets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_widgets.cpp; path = ../../imgui_widgets.cpp; sourceTree = "<group>"; };
4080A96B20B029B00036BA46 /* example_osx_opengl2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = example_osx_opengl2; sourceTree = BUILT_PRODUCTS_DIR; };
4080A98A20B02CD90036BA46 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = SOURCE_ROOT; };
@ -57,6 +59,7 @@
files = (
4080A9B520B034EA0036BA46 /* OpenGL.framework in Frameworks */,
4080A9B320B034E40036BA46 /* Cocoa.framework in Frameworks */,
05E31B59274EF0700083FCB6 /* GameController.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -95,6 +98,7 @@
4080A9B120B034E40036BA46 /* Frameworks */ = {
isa = PBXGroup;
children = (
05E31B57274EF0360083FCB6 /* GameController.framework */,
4080A9B420B034EA0036BA46 /* OpenGL.framework */,
4080A9B220B034E40036BA46 /* Cocoa.framework */,
);

View File

@ -58,7 +58,7 @@
//ImGui::StyleColorsClassic();
// Setup Platform/Renderer backends
ImGui_ImplOSX_Init();
ImGui_ImplOSX_Init(self);
ImGui_ImplOpenGL2_Init();
// Load Fonts
@ -146,12 +146,9 @@
animationTimer = [NSTimer scheduledTimerWithTimeInterval:0.017 target:self selector:@selector(animationTimerFired:) userInfo:nil repeats:YES];
}
-(void)reshape { [[self openGLContext] update]; [self updateAndDrawDemoView]; }
-(void)reshape { [super reshape]; [[self openGLContext] update]; [self updateAndDrawDemoView]; }
-(void)drawRect:(NSRect)bounds { [self updateAndDrawDemoView]; }
-(void)animationTimerFired:(NSTimer*)timer { [self setNeedsDisplay:YES]; }
-(BOOL)acceptsFirstResponder { return (YES); }
-(BOOL)becomeFirstResponder { return (YES); }
-(BOOL)resignFirstResponder { return (YES); }
-(void)dealloc { animationTimer = nil; }
//-----------------------------------------------------------------------------------

View File

@ -1,8 +1,11 @@
## 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
- You may also refer to our [Continuous Integration setup](https://github.com/ocornut/imgui/tree/master/.github/workflows) for Emscripten setup.
- Depending on your configuration, in Windows you may need to run `emsdk/emsdk_env.bat` in your console to access the Emscripten command-line tools.
- You may also refer to our [Continuous Integration setup](https://github.com/ocornut/imgui/tree/master/.github/workflows) for Emscripten setup.
- Then build using `make` while in the `example_emscripten_opengl3/` directory.
## How to Run
@ -15,6 +18,7 @@ _"Unfortunately several browsers (including Chrome, Safari, and Internet Explore
- 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`.
- If you are accessing the files over a network, certain browsers, such as Firefox, will restrict Gamepad API access to secure contexts only (e.g. https only).
## Obsolete features:

View File

@ -1,10 +1,24 @@
# How to Build
## 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.
- You may also refer to our [Continuous Integration setup](https://github.com/ocornut/imgui/tree/master/.github/workflows) for Emscripten setup.
- Then build using `make` while in the `example_emscripten_wgpu/` directory.
- Requires Emscripten 2.0.10 (December 2020) due to GLFW adaptations
- Requires recent Emscripten as WGPU is still a work-in-progress API.
## How to Run
To run on a local machine:
- Make sure your browse supports WGPU and it is enabled. WGPU is still WIP not enabled by default in most browser.
- `make serve` will use Python3 to spawn a local webserver, you can then browse http://localhost:8000 to access your build.
- Otherwise, generally you will need a local webserver:
- Quoting [https://emscripten.org/docs/getting_started](https://emscripten.org/docs/getting_started/Tutorial.html#generating-html):<br>
_"Unfortunately several browsers (including Chrome, Safari, and Internet Explorer) do not support file:// [XHR](https://emscripten.org/docs/site/glossary.html#term-xhr) requests, and cant load extra files needed by the HTML (like a .wasm file, or packaged file data as mentioned lower down). For these browsers youll need to serve the files using a [local webserver](https://emscripten.org/docs/getting_started/FAQ.html#faq-local-webserver) and then open http://localhost:8000/hello.html."_
- Emscripten SDK has a handy `emrun` command: `emrun web/example_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`.
- If you are accessing the files over a network, certain browsers, such as Firefox, will restrict Gamepad API access to secure contexts only (e.g. https only).

View File

@ -1,32 +0,0 @@
# This file is for configuration settings for your
# application.
#
# The syntax is similar to windows .ini files ie
#
# [GroupName]
# Setting = Value
#
# Which can be read by your application using
# e.g s3eConfigGetString("GroupName", "Setting", string)
#
# All settings must be documented in .config.txt files.
# New settings specific to this application should be
# documented in app.config.txt
#
# Some conditional operations are also permitted, see the
# S3E documentation for details.
[S3E]
MemSize=6000000
MemSizeDebug=6000000
DispFixRot=FixedLandscape
# emulate iphone 5 resolution, change these settings to emulate other display resolution
WinWidth=1136
WinHeight=640
[GX]
DataCacheSize=131070
[Util]
#MemoryBreakpoint=1282

View File

@ -1,124 +0,0 @@
// Dear ImGui: standalone example application for Marmalade
// 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
// Copyright (C) 2015 by Giovanni Zito
// This file is part of Dear ImGui
#include "imgui.h"
#include "imgui_impl_marmalade.h"
#include <stdio.h>
#include <s3eKeyboard.h>
#include <s3ePointer.h>
#include <IwGx.h>
int main(int, char**)
{
IwGxInit();
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
// Setup Platform/Renderer backends
ImGui_Marmalade_Init(true);
// 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 \\ !
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop
while (true)
{
if (s3eDeviceCheckQuitRequest())
break;
// Poll and handle inputs
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
s3eKeyboardUpdate();
s3ePointerUpdate();
// Start the Dear ImGui frame
ImGui_Marmalade_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();
IwGxSetColClear(clear_color.x * 255, clear_color.y * 255, clear_color.z * 255, clear_color.w * 255);
IwGxClear();
ImGui_Marmalade_RenderDrawData(ImGui::GetDrawData());
IwGxSwapBuffers();
s3eDeviceYield(0);
}
// Cleanup
ImGui_Marmalade_Shutdown();
ImGui::DestroyContext();
IwGxTerminate();
return 0;
}

View File

@ -1,47 +0,0 @@
#!/usr/bin/env mkb
# ImGui - standalone example application for Marmalade
# Copyright (C) 2015 by Giovanni Zito
# This file is part of ImGui
# https://github.com/ocornut/imgui
define IMGUI_DISABLE_INCLUDE_IMCONFIG_H
define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS
define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS
define _snprintf=snprintf
options
{
optimise-speed=1
}
includepaths
{
../..
../../backends
}
subprojects
{
iwgx
}
files
{
(.)
["imgui"]
../../imgui.cpp
../../imgui_demo.cpp
../../imgui_draw.cpp
../../imgui_tables.cpp
../../imgui_widgets.cpp
../../imconfig.h
../../imgui.h
../../imgui_internal.h
["imgui","Marmalade backend"]
../../backends/imgui_impl_marmalade.h
../../backends/imgui_impl_marmalade.cpp
main.cpp
}

1304
imgui.cpp

File diff suppressed because it is too large Load Diff

69
imgui.h
View File

@ -1,4 +1,4 @@
// dear imgui, v1.85
// dear imgui, v1.86
// (headers)
// Help:
@ -63,8 +63,8 @@ Index of this file:
// Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.85"
#define IMGUI_VERSION_NUM 18500
#define IMGUI_VERSION "1.86"
#define IMGUI_VERSION_NUM 18600
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE
@ -152,7 +152,7 @@ struct ImGuiContext; // Dear ImGui context (opaque structure, unl
struct ImGuiIO; // Main configuration and I/O between your application and ImGui
struct ImGuiInputTextCallbackData; // Shared state of InputText() when using custom ImGuiInputTextCallback (rare/advanced use)
struct ImGuiListClipper; // Helper to manually clip large list of items
struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame, used by IMGUI_ONCE_UPON_A_FRAME macro
struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame
struct ImGuiPayload; // User data payload for drag and drop operations
struct ImGuiSizeCallbackData; // Callback data when using SetNextWindowSizeConstraints() (rare/advanced use)
struct ImGuiStorage; // Helper for key->value storage
@ -869,7 +869,6 @@ namespace ImGui
IMGUI_API const char* GetStyleColorName(ImGuiCol idx); // get a string corresponding to the enum value (for display, saving, etc.).
IMGUI_API void SetStateStorage(ImGuiStorage* storage); // replace current window storage with our own (if you want to manipulate it yourself, typically clear subsection of it)
IMGUI_API ImGuiStorage* GetStateStorage();
IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can.
IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame
IMGUI_API void EndChildFrame(); // always call EndChildFrame() regardless of BeginChildFrame() return values (which indicates a collapsed/clipped window)
@ -897,9 +896,10 @@ namespace ImGui
// - You can also use regular integer: it is forever guaranteed that 0=Left, 1=Right, 2=Middle.
// - Dragging operations are only reported after mouse has moved a certain distance away from the initial clicking position (see 'lock_threshold' and 'io.MouseDraggingThreshold')
IMGUI_API bool IsMouseDown(ImGuiMouseButton button); // is mouse button held?
IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, bool repeat = false); // did mouse button clicked? (went from !Down to Down)
IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, bool repeat = false); // did mouse button clicked? (went from !Down to Down). Same as GetMouseClickedCount() == 1.
IMGUI_API bool IsMouseReleased(ImGuiMouseButton button); // did mouse button released? (went from Down to !Down)
IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button); // did mouse button double-clicked? (note that a double-click will also report IsMouseClicked() == true)
IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button); // did mouse button double-clicked? Same as GetMouseClickedCount() == 2. (note that a double-click will also report IsMouseClicked() == true)
IMGUI_API int GetMouseClickedCount(ImGuiMouseButton button); // return the number of successive mouse-clicks at the time where a click happen (otherwise 0).
IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true);// is mouse hovering given bounding rect (in screen space). clipped by current clipping settings, but disregarding of other consideration of focus/window ordering/popup-block.
IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); // by convention we use (-FLT_MAX,-FLT_MAX) to denote that there is no mouse available
IMGUI_API bool IsAnyMouseDown(); // is any mouse button held?
@ -954,7 +954,7 @@ enum ImGuiWindowFlags_
ImGuiWindowFlags_NoMove = 1 << 2, // Disable user moving the window
ImGuiWindowFlags_NoScrollbar = 1 << 3, // Disable scrollbars (window can still scroll with mouse or programmatically)
ImGuiWindowFlags_NoScrollWithMouse = 1 << 4, // Disable user vertically scrolling with mouse wheel. On child window, mouse wheel will be forwarded to the parent unless NoScrollbar is also set.
ImGuiWindowFlags_NoCollapse = 1 << 5, // Disable user collapsing window by double-clicking on it
ImGuiWindowFlags_NoCollapse = 1 << 5, // Disable user collapsing window by double-clicking on it. Also referred to as Window Menu Button (e.g. within a docking node).
ImGuiWindowFlags_AlwaysAutoResize = 1 << 6, // Resize every window to its content every frame
ImGuiWindowFlags_NoBackground = 1 << 7, // Disable drawing background color (WindowBg, etc.) and outside border. Similar as using SetNextWindowBgAlpha(0.0f).
ImGuiWindowFlags_NoSavedSettings = 1 << 8, // Never load/save settings in .ini file
@ -974,7 +974,7 @@ enum ImGuiWindowFlags_
ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus,
// [Internal]
ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!)
ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] On child window: allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows.
ImGuiWindowFlags_ChildWindow = 1 << 24, // Don't use! For internal use by BeginChild()
ImGuiWindowFlags_Tooltip = 1 << 25, // Don't use! For internal use by BeginTooltip()
ImGuiWindowFlags_Popup = 1 << 26, // Don't use! For internal use by BeginPopup()
@ -1742,7 +1742,7 @@ struct ImVector
inline void pop_back() { IM_ASSERT(Size > 0); Size--; }
inline void push_front(const T& v) { if (Size == 0) push_back(v); else insert(Data, v); }
inline T* erase(const T* it) { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(T)); Size--; return Data + off; }
inline T* erase(const T* it, const T* it_last){ IM_ASSERT(it >= Data && it < Data + Size && it_last > it && it_last <= Data + Size); const ptrdiff_t count = it_last - it; const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + count, ((size_t)Size - (size_t)off - count) * sizeof(T)); Size -= (int)count; return Data + off; }
inline T* erase(const T* it, const T* it_last){ IM_ASSERT(it >= Data && it < Data + Size && it_last > it && it_last <= Data + Size); const ptrdiff_t count = it_last - it; const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + count, ((size_t)Size - (size_t)off - (size_t)count) * sizeof(T)); Size -= (int)count; return Data + off; }
inline T* erase_unsorted(const T* it) { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; if (it < Data + Size - 1) memcpy(Data + off, Data + Size - 1, sizeof(T)); Size--; return Data + off; }
inline T* insert(const T* it, const T& v) { IM_ASSERT(it >= Data && it <= Data + Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(T)); memcpy(&Data[off], &v, sizeof(v)); Size++; return Data + off; }
inline bool contains(const T& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; }
@ -1930,12 +1930,13 @@ struct ImGuiIO
ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid)
ImVec2 MouseClickedPos[5]; // Position at time of clicking
double MouseClickedTime[5]; // Time of last click (used to figure out double-click)
bool MouseClicked[5]; // Mouse button went from !Down to Down
bool MouseDoubleClicked[5]; // Has mouse button been double-clicked?
bool MouseClicked[5]; // Mouse button went from !Down to Down (same as MouseClickedCount[x] != 0)
bool MouseDoubleClicked[5]; // Has mouse button been double-clicked? (same as MouseClickedCount[x] == 2)
ImU16 MouseClickedCount[5]; // == 0 (not clicked), == 1 (same as MouseClicked[]), == 2 (double-clicked), == 3 (triple-clicked) etc. when going from !Down to Down
ImU16 MouseClickedLastCount[5]; // Count successive number of clicks. Stays valid after mouse release. Reset after another click is done.
bool MouseReleased[5]; // Mouse button went from Down to !Down
bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds.
bool MouseDownOwnedUnlessPopupClose[5];//Track if button was clicked inside a dear imgui window.
bool MouseDownWasDoubleClick[5]; // Track if button down was a double-click
float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked)
float MouseDownDurationPrev[5]; // Previous time the mouse button has been down
ImVec2 MouseDragMaxDistanceAbs[5]; // Maximum distance, absolute, on each axis, of how much mouse has traveled from the clicking point
@ -2170,10 +2171,12 @@ struct ImGuiStorage
};
// Helper: Manually clip large list of items.
// If you are submitting lots of evenly spaced items and you have a random access to the list, you can perform coarse
// clipping based on visibility to save yourself from processing those items at all.
// If you have lots evenly spaced items and you have a random access to the list, you can perform coarse
// clipping based on visibility to only submit items that are in view.
// The clipper calculates the range of visible items and advance the cursor to compensate for the non-visible items we have skipped.
// (Dear ImGui already clip items based on their bounds but it needs to measure text size to do so, whereas manual coarse clipping before submission makes this cost and your own data fetching/submission cost almost null)
// (Dear ImGui already clip items based on their bounds but: it needs to first layout the item to do so, and generally
// fetching/submitting your own data incurs additional cost. Coarse clipping using ImGuiListClipper allows you to easily
// scale using lists with tens of thousands of items without a problem)
// Usage:
// ImGuiListClipper clipper;
// clipper.Begin(1000); // We have 1000 elements, evenly spaced.
@ -2182,30 +2185,30 @@ struct ImGuiStorage
// ImGui::Text("line number %d", i);
// Generally what happens is:
// - Clipper lets you process the first element (DisplayStart = 0, DisplayEnd = 1) regardless of it being visible or not.
// - User code submit one element.
// - User code submit that one element.
// - Clipper can measure the height of the first element
// - Clipper calculate the actual range of elements to display based on the current clipping rectangle, position the cursor before the first visible element.
// - User code submit visible elements.
// - The clipper also handles various subtleties related to keyboard/gamepad navigation, wrapping etc.
struct ImGuiListClipper
{
int DisplayStart;
int DisplayEnd;
// [Internal]
int ItemsCount;
int StepNo;
int ItemsFrozen;
float ItemsHeight;
float StartPosY;
IMGUI_API ImGuiListClipper();
IMGUI_API ~ImGuiListClipper();
int DisplayStart; // First item to display, updated by each call to Step()
int DisplayEnd; // End of items to display (exclusive)
int ItemsCount; // [Internal] Number of items
float ItemsHeight; // [Internal] Height of item after a first step and item submission can calculate it
float StartPosY; // [Internal] Cursor position at the time of Begin() or after table frozen rows are all processed
void* TempData; // [Internal] Internal data
// items_count: Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step)
// items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing().
IMGUI_API void Begin(int items_count, float items_height = -1.0f); // Automatically called by constructor if you passed 'items_count' or by Step() in Step 1.
IMGUI_API void End(); // Automatically called on the last call of Step() that returns false.
IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items.
IMGUI_API ImGuiListClipper();
IMGUI_API ~ImGuiListClipper();
IMGUI_API void Begin(int items_count, float items_height = -1.0f);
IMGUI_API void End(); // Automatically called on the last call of Step() that returns false.
IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items.
// Call ForceDisplayRangeByIndices() before first call to Step() if you need a range of items to be displayed regardless of visibility.
IMGUI_API void ForceDisplayRangeByIndices(int item_min, int item_max); // item_max is exclusive e.g. use (42, 42+1) to make item 42 always visible BUT due to alignment/padding of certain items it is likely that an extra item may be included on either end of the display range.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
inline ImGuiListClipper(int items_count, float items_height = -1.0f) { memset(this, 0, sizeof(*this)); ItemsCount = -1; Begin(items_count, items_height); } // [removed in 1.79]
@ -2828,6 +2831,8 @@ struct ImGuiViewport
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
namespace ImGui
{
// OBSOLETED in 1.86 (from November 2021)
IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Calculate coarse clipping for large list of evenly sized items. Prefer using ImGuiListClipper.
// OBSOLETED in 1.85 (from August 2021)
static inline float GetWindowContentRegionWidth() { return GetWindowContentRegionMax().x - GetWindowContentRegionMin().x; }
// OBSOLETED in 1.81 (from February 2021)

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
// dear imgui, v1.85
// dear imgui, v1.86
// (drawing and font code)
/*
@ -473,6 +473,7 @@ void ImDrawList::_PopUnusedDrawCmd()
void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
{
IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
IM_ASSERT(curr_cmd->UserCallback == NULL);
if (curr_cmd->ElemCount != 0)
@ -494,6 +495,7 @@ void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
// Try to merge two last draw commands
void ImDrawList::_TryMergeDrawCmds()
{
IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
ImDrawCmd* prev_cmd = curr_cmd - 1;
if (ImDrawCmd_HeaderCompare(curr_cmd, prev_cmd) == 0 && curr_cmd->UserCallback == NULL && prev_cmd->UserCallback == NULL)
@ -508,6 +510,7 @@ void ImDrawList::_TryMergeDrawCmds()
void ImDrawList::_OnChangedClipRect()
{
// If current command is used with different settings we need to add a new command
IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
if (curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &_CmdHeader.ClipRect, sizeof(ImVec4)) != 0)
{
@ -530,6 +533,7 @@ void ImDrawList::_OnChangedClipRect()
void ImDrawList::_OnChangedTextureID()
{
// If current command is used with different settings we need to add a new command
IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
if (curr_cmd->ElemCount != 0 && curr_cmd->TextureId != _CmdHeader.TextureId)
{
@ -553,6 +557,7 @@ void ImDrawList::_OnChangedVtxOffset()
{
// We don't need to compare curr_cmd->VtxOffset != _CmdHeader.VtxOffset because we know it'll be different at the time we call this.
_VtxCurrentIdx = 0;
IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
//IM_ASSERT(curr_cmd->VtxOffset != _CmdHeader.VtxOffset); // See #3349
if (curr_cmd->ElemCount != 0)
@ -1919,37 +1924,38 @@ ImFontConfig::ImFontConfig()
// A work of art lies ahead! (. = white layer, X = black layer, others are blank)
// The 2x2 white texels on the top left are the ones we'll use everywhere in Dear ImGui to render filled shapes.
const int FONT_ATLAS_DEFAULT_TEX_DATA_W = 108; // Actual texture will be 2 times that + 1 spacing.
// (This is used when io.MouseDrawCursor = true)
const int FONT_ATLAS_DEFAULT_TEX_DATA_W = 122; // Actual texture will be 2 times that + 1 spacing.
const int FONT_ATLAS_DEFAULT_TEX_DATA_H = 27;
static const char FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[FONT_ATLAS_DEFAULT_TEX_DATA_W * FONT_ATLAS_DEFAULT_TEX_DATA_H + 1] =
{
"..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX- XX "
"..- -X.....X- X.X - X.X -X.....X - X.....X- X..X "
"--- -XXX.XXX- X...X - X...X -X....X - X....X- X..X "
"X - X.X - X.....X - X.....X -X...X - X...X- X..X "
"XX - X.X -X.......X- X.......X -X..X.X - X.X..X- X..X "
"X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X- X..XXX "
"X..X - X.X - X.X - X.X -XX X.X - X.X XX- X..X..XXX "
"X...X - X.X - X.X - XX X.X XX - X.X - X.X - X..X..X..XX "
"X....X - X.X - X.X - X.X X.X X.X - X.X - X.X - X..X..X..X.X "
"X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X -XXX X..X..X..X..X"
"X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X -X..XX........X..X"
"X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X -X...X...........X"
"X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X - X..............X"
"X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X - X.............X"
"X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X - X.............X"
"X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X - X............X"
"X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX - X...........X "
"X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------- X..........X "
"X.X X..X - -X.......X- X.......X - XX XX - - X..........X "
"XX X..X - - X.....X - X.....X - X.X X.X - - X........X "
" X..X - X...X - X...X - X..X X..X - - X........X "
" XX - X.X - X.X - X...XXXXXXXXXXXXX...X - - XXXXXXXXXX "
"------------ - X - X -X.....................X- ------------------"
" ----------------------------------- X...XXXXXXXXXXXXX...X - "
" - X..X X..X - "
" - X.X X.X - "
" - XX XX - "
"..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX- XX - XX XX "
"..- -X.....X- X.X - X.X -X.....X - X.....X- X..X -X..X X..X"
"--- -XXX.XXX- X...X - X...X -X....X - X....X- X..X -X...X X...X"
"X - X.X - X.....X - X.....X -X...X - X...X- X..X - X...X X...X "
"XX - X.X -X.......X- X.......X -X..X.X - X.X..X- X..X - X...X...X "
"X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X- X..XXX - X.....X "
"X..X - X.X - X.X - X.X -XX X.X - X.X XX- X..X..XXX - X...X "
"X...X - X.X - X.X - XX X.X XX - X.X - X.X - X..X..X..XX - X.X "
"X....X - X.X - X.X - X.X X.X X.X - X.X - X.X - X..X..X..X.X - X...X "
"X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X -XXX X..X..X..X..X- X.....X "
"X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X -X..XX........X..X- X...X...X "
"X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X -X...X...........X- X...X X...X "
"X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X - X..............X-X...X X...X"
"X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X - X.............X-X..X X..X"
"X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X - X.............X- XX XX "
"X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X - X............X--------------"
"X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX - X...........X - "
"X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------- X..........X - "
"X.X X..X - -X.......X- X.......X - XX XX - - X..........X - "
"XX X..X - - X.....X - X.....X - X.X X.X - - X........X - "
" X..X - - X...X - X...X - X..X X..X - - X........X - "
" XX - - X.X - X.X - X...XXXXXXXXXXXXX...X - - XXXXXXXXXX - "
"------------- - X - X -X.....................X- ------------------- "
" ----------------------------------- X...XXXXXXXXXXXXX...X - "
" - X..X X..X - "
" - X.X X.X - "
" - XX XX - "
};
static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_COUNT][3] =
@ -1963,6 +1969,7 @@ static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_COUNT][3
{ ImVec2(73,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNESW
{ ImVec2(55,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNWSE
{ ImVec2(91,0), ImVec2(17,22), ImVec2( 5, 0) }, // ImGuiMouseCursor_Hand
{ ImVec2(109,0),ImVec2(13,15), ImVec2( 6, 7) }, // ImGuiMouseCursor_NotAllowed
};
ImFontAtlas::ImFontAtlas()
@ -3073,8 +3080,8 @@ void ImFontGlyphRangesBuilder::AddText(const char* text, const char* text_end)
void ImFontGlyphRangesBuilder::AddRanges(const ImWchar* ranges)
{
for (; ranges[0]; ranges += 2)
for (ImWchar c = ranges[0]; c <= ranges[1]; c++)
AddChar(c);
for (unsigned int c = ranges[0]; c <= ranges[1] && c <= IM_UNICODE_CODEPOINT_MAX; c++) //-V560
AddChar((ImWchar)c);
}
void ImFontGlyphRangesBuilder::BuildRanges(ImVector<ImWchar>* out_ranges)
@ -3899,10 +3906,10 @@ void ImGui::RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect
const bool fill_R = (inner.Max.x < outer.Max.x);
const bool fill_U = (inner.Min.y > outer.Min.y);
const bool fill_D = (inner.Max.y < outer.Max.y);
if (fill_L) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Min.y), ImVec2(inner.Min.x, inner.Max.y), col, rounding, (fill_U ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomLeft));
if (fill_R) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Min.y), ImVec2(outer.Max.x, inner.Max.y), col, rounding, (fill_U ? 0 : ImDrawFlags_RoundCornersTopRight) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomRight));
if (fill_U) draw_list->AddRectFilled(ImVec2(inner.Min.x, outer.Min.y), ImVec2(inner.Max.x, inner.Min.y), col, rounding, (fill_L ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersTopRight));
if (fill_D) draw_list->AddRectFilled(ImVec2(inner.Min.x, inner.Max.y), ImVec2(inner.Max.x, outer.Max.y), col, rounding, (fill_L ? 0 : ImDrawFlags_RoundCornersBottomLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersBottomRight));
if (fill_L) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Min.y), ImVec2(inner.Min.x, inner.Max.y), col, rounding, ImDrawFlags_RoundCornersNone | (fill_U ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomLeft));
if (fill_R) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Min.y), ImVec2(outer.Max.x, inner.Max.y), col, rounding, ImDrawFlags_RoundCornersNone | (fill_U ? 0 : ImDrawFlags_RoundCornersTopRight) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomRight));
if (fill_U) draw_list->AddRectFilled(ImVec2(inner.Min.x, outer.Min.y), ImVec2(inner.Max.x, inner.Min.y), col, rounding, ImDrawFlags_RoundCornersNone | (fill_L ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersTopRight));
if (fill_D) draw_list->AddRectFilled(ImVec2(inner.Min.x, inner.Max.y), ImVec2(inner.Max.x, outer.Max.y), col, rounding, ImDrawFlags_RoundCornersNone | (fill_L ? 0 : ImDrawFlags_RoundCornersBottomLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersBottomRight));
if (fill_L && fill_U) draw_list->AddRectFilled(ImVec2(outer.Min.x, outer.Min.y), ImVec2(inner.Min.x, inner.Min.y), col, rounding, ImDrawFlags_RoundCornersTopLeft);
if (fill_R && fill_U) draw_list->AddRectFilled(ImVec2(inner.Max.x, outer.Min.y), ImVec2(outer.Max.x, inner.Min.y), col, rounding, ImDrawFlags_RoundCornersTopRight);
if (fill_L && fill_D) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Max.y), ImVec2(inner.Min.x, outer.Max.y), col, rounding, ImDrawFlags_RoundCornersBottomLeft);

View File

@ -1,4 +1,4 @@
// dear imgui, v1.85
// dear imgui, v1.86
// (internal structures/api)
// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!
@ -18,6 +18,7 @@ Index of this file:
// [SECTION] Generic helpers
// [SECTION] ImDrawList support
// [SECTION] Widgets support: flags, enums, data structures
// [SECTION] Clipper support
// [SECTION] Navigation support
// [SECTION] Columns support
// [SECTION] Multi-select support
@ -252,12 +253,19 @@ namespace ImStb
#endif
// Debug Tools
// Use 'Metrics->Tools->Item Picker' to break into the call-stack of a specific item.
// Use 'Metrics/Debugger->Tools->Item Picker' to break into the call-stack of a specific item.
// This will call IM_DEBUG_BREAK() which you may redefine yourself. See https://github.com/scottt/debugbreak for more reference.
#ifndef IM_DEBUG_BREAK
#if defined(__clang__)
#define IM_DEBUG_BREAK() __builtin_debugtrap()
#elif defined (_MSC_VER)
#if defined (_MSC_VER)
#define IM_DEBUG_BREAK() __debugbreak()
#elif defined(__clang__)
#define IM_DEBUG_BREAK() __builtin_debugtrap()
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
#define IM_DEBUG_BREAK() __asm__ volatile("int $0x03")
#elif defined(__GNUC__) && defined(__thumb__)
#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xde01")
#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__)
#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xe7f001f0");
#else
#define IM_DEBUG_BREAK() IM_ASSERT(0) // It is expected that you define IM_DEBUG_BREAK() into something that will break nicely in a debugger!
#endif
@ -294,7 +302,9 @@ static inline ImGuiID ImHash(const void* data, int size, ImU32 seed = 0) { ret
#endif
// Helpers: Sorting
#define ImQsort qsort
#ifndef ImQsort
static inline void ImQsort(void* base, size_t count, size_t size_of_element, int(IMGUI_CDECL *compare_func)(void const*, void const*)) { if (count > 1) qsort(base, count, size_of_element, compare_func); }
#endif
// Helpers: Color Blending
IMGUI_API ImU32 ImAlphaBlendColors(ImU32 col_a, ImU32 col_b);
@ -401,8 +411,8 @@ static inline double ImLog(double x) { return log(x); }
static inline int ImAbs(int x) { return x < 0 ? -x : x; }
static inline float ImAbs(float x) { return fabsf(x); }
static inline double ImAbs(double x) { return fabs(x); }
static inline float ImSign(float x) { return (x < 0.0f) ? -1.0f : ((x > 0.0f) ? 1.0f : 0.0f); } // Sign operator - returns -1, 0 or 1 based on sign of argument
static inline double ImSign(double x) { return (x < 0.0) ? -1.0 : ((x > 0.0) ? 1.0 : 0.0); }
static inline float ImSign(float x) { return (x < 0.0f) ? -1.0f : (x > 0.0f) ? 1.0f : 0.0f; } // Sign operator - returns -1, 0 or 1 based on sign of argument
static inline double ImSign(double x) { return (x < 0.0) ? -1.0 : (x > 0.0) ? 1.0 : 0.0; }
#ifdef IMGUI_ENABLE_SSE
static inline float ImRsqrt(float x) { return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(x))); }
#else
@ -438,6 +448,7 @@ static inline float ImDot(const ImVec2& a, const ImVec2& b)
static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; }
static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
static inline bool ImIsFloatAboveGuaranteedIntegerPrecision(float f) { return f <= -16777216 || f >= 16777216; }
IM_MSVC_RUNTIME_CHECKS_RESTORE
// Helpers: Geometry
@ -1019,8 +1030,6 @@ struct IMGUI_API ImGuiInputTextState
bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection
bool Edited; // edited this frame
ImGuiInputTextFlags Flags; // copy of InputText() flags
ImGuiInputTextCallback UserCallback; // "
void* UserCallbackData; // "
ImGuiInputTextState() { memset(this, 0, sizeof(*this)); }
void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); }
@ -1162,6 +1171,35 @@ struct ImGuiPtrOrIndex
ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; }
};
//-----------------------------------------------------------------------------
// [SECTION] Clipper support
//-----------------------------------------------------------------------------
struct ImGuiListClipperRange
{
int Min;
int Max;
bool PosToIndexConvert; // Begin/End are absolute position (will be converted to indices later)
ImS8 PosToIndexOffsetMin; // Add to Min after converting to indices
ImS8 PosToIndexOffsetMax; // Add to Min after converting to indices
static ImGuiListClipperRange FromIndices(int min, int max) { ImGuiListClipperRange r = { min, max, false, 0, 0 }; return r; }
static ImGuiListClipperRange FromPositions(float y1, float y2, int off_min, int off_max) { ImGuiListClipperRange r = { (int)y1, (int)y2, true, (ImS8)off_min, (ImS8)off_max }; return r; }
};
// Temporary clipper data, buffers shared/reused between instances
struct ImGuiListClipperData
{
ImGuiListClipper* ListClipper;
float LossynessOffset;
int StepNo;
int ItemsFrozen;
ImVector<ImGuiListClipperRange> Ranges;
ImGuiListClipperData() { memset(this, 0, sizeof(*this)); }
void Reset(ImGuiListClipper* clipper) { ListClipper = clipper; StepNo = ItemsFrozen = 0; Ranges.resize(0); }
};
//-----------------------------------------------------------------------------
// [SECTION] Navigation support
//-----------------------------------------------------------------------------
@ -1201,9 +1239,10 @@ enum ImGuiNavHighlightFlags_
enum ImGuiNavDirSourceFlags_
{
ImGuiNavDirSourceFlags_None = 0,
ImGuiNavDirSourceFlags_Keyboard = 1 << 0,
ImGuiNavDirSourceFlags_PadDPad = 1 << 1,
ImGuiNavDirSourceFlags_PadLStick = 1 << 2
ImGuiNavDirSourceFlags_RawKeyboard = 1 << 0, // Raw keyboard (not pulled from nav), faciliate use of some functions before we can unify nav and keys
ImGuiNavDirSourceFlags_Keyboard = 1 << 1,
ImGuiNavDirSourceFlags_PadDPad = 1 << 2,
ImGuiNavDirSourceFlags_PadLStick = 1 << 3
};
enum ImGuiNavMoveFlags_
@ -1218,9 +1257,10 @@ enum ImGuiNavMoveFlags_
ImGuiNavMoveFlags_ScrollToEdgeY = 1 << 6, // Force scrolling to min/max (used by Home/End) // FIXME-NAV: Aim to remove or reword, probably unnecessary
ImGuiNavMoveFlags_Forwarded = 1 << 7,
ImGuiNavMoveFlags_DebugNoResult = 1 << 8, // Dummy scoring for debug purpose, don't apply result
ImGuiNavMoveFlags_Tabbing = 1 << 9, // == Focus + Activate if item is Inputable + DontChangeNavHighlight
ImGuiNavMoveFlags_Activate = 1 << 10,
ImGuiNavMoveFlags_DontSetNavHighlight = 1 << 11 // Do not alter the visible state of keyboard vs mouse nav highlight
ImGuiNavMoveFlags_FocusApi = 1 << 9,
ImGuiNavMoveFlags_Tabbing = 1 << 10, // == Focus + Activate if item is Inputable + DontChangeNavHighlight
ImGuiNavMoveFlags_Activate = 1 << 11,
ImGuiNavMoveFlags_DontSetNavHighlight = 1 << 12 // Do not alter the visible state of keyboard vs mouse nav highlight
};
enum ImGuiNavLayer
@ -1540,6 +1580,7 @@ struct ImGuiContext
ImVector<ImGuiGroupData>GroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin()
ImVector<ImGuiPopupData>OpenPopupStack; // Which popups are open (persistent)
ImVector<ImGuiPopupData>BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame)
int BeginMenuCount;
// Viewports
ImVector<ImGuiViewportP*> Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData.
@ -1553,7 +1594,6 @@ struct ImGuiContext
ImGuiID NavActivatePressedId; // ~~ IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0
ImGuiID NavActivateInputId; // ~~ IsNavInputPressed(ImGuiNavInput_Input) ? NavId : 0; ImGuiActivateFlags_PreferInput will be set and NavActivateId will be 0.
ImGuiActivateFlags NavActivateFlags;
ImGuiID NavJustTabbedId; // Just tabbed to this id.
ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest).
ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest).
ImGuiKeyModFlags NavJustMovedToKeyMods;
@ -1561,7 +1601,6 @@ struct ImGuiContext
ImGuiActivateFlags NavNextActivateFlags;
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard.
ImGuiNavLayer NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later.
int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing
bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid
bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default)
bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover)
@ -1583,11 +1622,14 @@ struct ImGuiContext
ImGuiDir NavMoveDirForDebug;
ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename?
ImRect NavScoringRect; // Rectangle used for scoring, in screen space. Based of window->NavRectRel[], modified for directional navigation scoring.
ImRect NavScoringNoClipRect; // Some nav operations (such as PageUp/PageDown) enforce a region which clipper will attempt to always keep submitted
int NavScoringDebugCount; // Metrics for debugging
int NavTabbingInputableRemaining; // >0 when counting items for tabbing
int NavTabbingDir; // Generally -1 or +1, 0 when tabbing without a nav id
int NavTabbingCounter; // >0 when counting items for tabbing
ImGuiNavItemData NavMoveResultLocal; // Best move request candidate within NavWindow
ImGuiNavItemData NavMoveResultLocalVisible; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
ImGuiNavItemData NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
ImGuiNavItemData NavTabbingResultFirst; // First tabbing request candidate within NavWindow and flattened hierarchy
// Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
ImGuiWindow* NavWindowingTarget; // Target window when doing CTRL+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most!
@ -1597,13 +1639,6 @@ struct ImGuiContext
float NavWindowingHighlightAlpha;
bool NavWindowingToggleLayer;
// Legacy Focus/Tabbing system (older than Nav, active even if Nav is disabled, misnamed. FIXME-NAV: This needs a redesign!)
ImGuiWindow* TabFocusRequestCurrWindow; //
ImGuiWindow* TabFocusRequestNextWindow; //
int TabFocusRequestCurrCounterTabStop; // Tab item being requested for focus, stored as an index
int TabFocusRequestNextCounterTabStop; // "
bool TabFocusPressed; // Set in NewFrame() when user pressed Tab
// Render
float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list)
ImGuiMouseCursor MouseCursor;
@ -1627,11 +1662,15 @@ struct ImGuiContext
ImVector<unsigned char> DragDropPayloadBufHeap; // We don't expose the ImVector<> directly, ImGuiPayload only holds pointer+size
unsigned char DragDropPayloadBufLocal[16]; // Local buffer for small payloads
// Clipper
int ClipperTempDataStacked;
ImVector<ImGuiListClipperData> ClipperTempData;
// Table
ImGuiTable* CurrentTable;
int CurrentTableStackIdx;
ImPool<ImGuiTable> Tables;
ImVector<ImGuiTableTempData> TablesTempDataStack;
int TablesTempDataStacked; // Temporary table data size (because we leave previous instances undestructed, we generally don't use TablesTempData.Size)
ImVector<ImGuiTableTempData> TablesTempData; // Temporary table data (buffers reused/shared across instances, support nesting)
ImPool<ImGuiTable> Tables; // Persistent table data
ImVector<float> TablesLastTimeActive; // Last used timestamp of each tables (SOA, for efficient GC)
ImVector<ImDrawChannel> DrawChannelsTempMergeBuffer;
@ -1763,15 +1802,15 @@ struct ImGuiContext
LastActiveIdTimer = 0.0f;
CurrentItemFlags = ImGuiItemFlags_None;
BeginMenuCount = 0;
NavWindow = NULL;
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavActivateInputId = 0;
NavJustTabbedId = NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
NavJustMovedToKeyMods = ImGuiKeyModFlags_None;
NavInputSource = ImGuiInputSource_None;
NavLayer = ImGuiNavLayer_Main;
NavIdTabCounter = INT_MAX;
NavIdIsAlive = false;
NavMousePosDirty = false;
NavDisableHighlight = true;
@ -1788,17 +1827,13 @@ struct ImGuiContext
NavMoveKeyMods = ImGuiKeyModFlags_None;
NavMoveDir = NavMoveDirForDebug = NavMoveClipDir = ImGuiDir_None;
NavScoringDebugCount = 0;
NavTabbingInputableRemaining = 0;
NavTabbingDir = 0;
NavTabbingCounter = 0;
NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL;
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
NavWindowingToggleLayer = false;
TabFocusRequestCurrWindow = TabFocusRequestNextWindow = NULL;
TabFocusRequestCurrCounterTabStop = INT_MAX;
TabFocusRequestNextCounterTabStop = INT_MAX;
TabFocusPressed = false;
DimBgRatio = 0.0f;
MouseCursor = ImGuiMouseCursor_Arrow;
@ -1814,8 +1849,10 @@ struct ImGuiContext
DragDropHoldJustPressedId = 0;
memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal));
ClipperTempDataStacked = 0;
CurrentTable = NULL;
CurrentTableStackIdx = -1;
TablesTempDataStacked = 0;
CurrentTabBar = NULL;
TempInputId = 0;
@ -1882,6 +1919,7 @@ struct IMGUI_API ImGuiWindowTempData
ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.)
ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API.
ImVec1 GroupOffset;
ImVec2 CursorStartPosLossyness;// Record the loss of precision of CursorStartPos due to really large scrolling amount. This is used by clipper to compensentate and fix the most common use case of large scroll area.
// Keyboard/Gamepad navigation
ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1)
@ -1903,7 +1941,6 @@ struct IMGUI_API ImGuiWindowTempData
int CurrentTableIdx; // Current table index (into g.Tables)
ImGuiLayoutType LayoutType;
ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin()
int FocusCounterTabStop; // (Legacy Focus/Tabbing system) Same, but only count widgets which you can Tab through.
// Local parameters stacks
// We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings.
@ -1947,6 +1984,7 @@ struct IMGUI_API ImGuiWindow
bool Appearing; // Set during the frame where the window is appearing (or re-appearing)
bool Hidden; // Do not display (== HiddenFrames*** > 0)
bool IsFallbackWindow; // Set on the "Debug##Default" window.
bool IsExplicitChild; // Set when passed _ChildWindow, left to false by BeginDocked()
bool HasCloseButton; // Set when the window has a close button (p_open != NULL)
signed char ResizeBorderHeld; // Current border being held for resize (-1: none, otherwise 0-3)
short BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs)
@ -1994,6 +2032,7 @@ struct IMGUI_API ImGuiWindow
ImDrawList* DrawList; // == &DrawListInst (for backward compatibility reason with code using imgui_internal.h we keep this a pointer)
ImDrawList DrawListInst;
ImGuiWindow* ParentWindow; // If we are a child _or_ popup _or_ docked window, this is pointing to our parent. Otherwise NULL.
ImGuiWindow* ParentWindowInBeginStack;
ImGuiWindow* RootWindow; // Point to ourself or first ancestor that is not a child window. Doesn't cross through popups/dock nodes.
ImGuiWindow* RootWindowPopupTree; // Point to ourself or first ancestor that is not a child window. Cross through popups parent<>child.
ImGuiWindow* RootWindowForTitleBarHighlight; // Point to ourself or first ancestor which will display TitleBgActive color when this window is active.
@ -2067,7 +2106,7 @@ struct ImGuiTabItem
};
// Storage for a tab bar (sizeof() 152 bytes)
struct ImGuiTabBar
struct IMGUI_API ImGuiTabBar
{
ImVector<ImGuiTabItem> Tabs;
ImGuiTabBarFlags Flags;
@ -2192,7 +2231,7 @@ struct ImGuiTableCellData
};
// FIXME-TABLE: more transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData
struct ImGuiTable
struct IMGUI_API ImGuiTable
{
ImGuiID ID;
ImGuiTableFlags Flags;
@ -2298,14 +2337,14 @@ struct ImGuiTable
bool MemoryCompacted;
bool HostSkipItems; // Backup of InnerWindow->SkipItem at the end of BeginTable(), because we will overwrite InnerWindow->SkipItem on a per-column basis
IMGUI_API ImGuiTable() { memset(this, 0, sizeof(*this)); LastFrameActive = -1; }
IMGUI_API ~ImGuiTable() { IM_FREE(RawData); }
ImGuiTable() { memset(this, 0, sizeof(*this)); LastFrameActive = -1; }
~ImGuiTable() { IM_FREE(RawData); }
};
// Transient data that are only needed between BeginTable() and EndTable(), those buffers are shared (1 per level of stacked table).
// - Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure.
// - We also leave out of this structure data that tend to be particularly useful for debugging/metrics.
struct ImGuiTableTempData
struct IMGUI_API ImGuiTableTempData
{
int TableIndex; // Index in g.Tables.Buf[] pool
float LastTimeActive; // Last timestamp this structure was used
@ -2322,7 +2361,7 @@ struct ImGuiTableTempData
float HostBackupItemWidth; // Backup of OuterWindow->DC.ItemWidth at the end of BeginTable()
int HostBackupItemWidthStackSize;//Backup of OuterWindow->DC.ItemWidthStack.Size at the end of BeginTable()
IMGUI_API ImGuiTableTempData() { memset(this, 0, sizeof(*this)); LastTimeActive = -1.0f; }
ImGuiTableTempData() { memset(this, 0, sizeof(*this)); LastTimeActive = -1.0f; }
};
// sizeof() ~ 12
@ -2382,12 +2421,15 @@ namespace ImGui
IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window);
IMGUI_API ImVec2 CalcWindowNextAutoFitSize(ImGuiWindow* window);
IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent, bool popup_hierarchy);
IMGUI_API bool IsWindowWithinBeginStackOf(ImGuiWindow* window, ImGuiWindow* potential_parent);
IMGUI_API bool IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below);
IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window);
IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0);
IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0);
IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0);
IMGUI_API void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size);
inline ImRect WindowRectAbsToRel(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x - off.x, r.Min.y - off.y, r.Max.x - off.x, r.Max.y - off.y); }
inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); }
// Windows: Display Order and Focus Order
IMGUI_API void FocusWindow(ImGuiWindow* window);
@ -2395,6 +2437,9 @@ namespace ImGui
IMGUI_API void BringWindowToFocusFront(ImGuiWindow* window);
IMGUI_API void BringWindowToDisplayFront(ImGuiWindow* window);
IMGUI_API void BringWindowToDisplayBack(ImGuiWindow* window);
IMGUI_API void BringWindowToDisplayBehind(ImGuiWindow* window, ImGuiWindow* above_window);
IMGUI_API int FindWindowDisplayIndex(ImGuiWindow* window);
IMGUI_API ImGuiWindow* FindBottomMostVisibleWindowWithinBeginStack(ImGuiWindow* window);
// Fonts, drawing
IMGUI_API void SetCurrentFont(ImFont* font);
@ -2463,8 +2508,8 @@ namespace ImGui
IMGUI_API void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f);
IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL, ImGuiItemFlags extra_flags = 0);
IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
IMGUI_API void ItemInputable(ImGuiWindow* window, ImGuiID id);
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id);
IMGUI_API void SetLastItemData(ImGuiID item_id, ImGuiItemFlags in_flags, ImGuiItemStatusFlags status_flags, const ImRect& item_rect);
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h);
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
IMGUI_API void PushMultiItemsWidths(int components, float width_full);
@ -2501,9 +2546,10 @@ namespace ImGui
IMGUI_API void ClosePopupsExceptModals();
IMGUI_API bool IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags);
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags);
IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, ImGuiTooltipFlags tooltip_flags);
IMGUI_API void BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags);
IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window);
IMGUI_API ImGuiWindow* GetTopMostPopupModal();
IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal();
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
@ -2523,7 +2569,7 @@ namespace ImGui
IMGUI_API bool NavMoveRequestButNoResultYet();
IMGUI_API void NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
IMGUI_API void NavMoveRequestResolveWithLastItem();
IMGUI_API void NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result);
IMGUI_API void NavMoveRequestCancel();
IMGUI_API void NavMoveRequestApplyResult();
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
@ -2671,7 +2717,7 @@ namespace ImGui
IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2& pos);
IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0);
IMGUI_API void Scrollbar(ImGuiAxis axis);
IMGUI_API bool ScrollbarEx(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float avail_v, float contents_v, ImDrawFlags flags);
IMGUI_API bool ScrollbarEx(const ImRect& bb, ImGuiID id, ImGuiAxis axis, ImS64* p_scroll_v, ImS64 avail_v, ImS64 contents_v, ImDrawFlags flags);
IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec2& padding, const ImVec4& bg_col, const ImVec4& tint_col);
IMGUI_API ImRect GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis);
IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis);
@ -2751,6 +2797,7 @@ namespace ImGui
IMGUI_API void DebugNodeWindow(ImGuiWindow* window, const char* label);
IMGUI_API void DebugNodeWindowSettings(ImGuiWindowSettings* settings);
IMGUI_API void DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* label);
IMGUI_API void DebugNodeWindowsListByBeginStackParent(ImGuiWindow** windows, int windows_size, ImGuiWindow* parent_in_begin_stack);
IMGUI_API void DebugNodeViewport(ImGuiViewportP* viewport);
IMGUI_API void DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport, const ImRect& bb);

View File

@ -1,4 +1,4 @@
// dear imgui, v1.85
// dear imgui, v1.86
// (tables and columns code)
/*
@ -340,10 +340,9 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
// Acquire temporary buffers
const int table_idx = g.Tables.GetIndex(table);
g.CurrentTableStackIdx++;
if (g.CurrentTableStackIdx + 1 > g.TablesTempDataStack.Size)
g.TablesTempDataStack.resize(g.CurrentTableStackIdx + 1, ImGuiTableTempData());
ImGuiTableTempData* temp_data = table->TempData = &g.TablesTempDataStack[g.CurrentTableStackIdx];
if (++g.TablesTempDataStacked > g.TablesTempData.Size)
g.TablesTempData.resize(g.TablesTempDataStacked, ImGuiTableTempData());
ImGuiTableTempData* temp_data = table->TempData = &g.TablesTempData[g.TablesTempDataStacked - 1];
temp_data->TableIndex = table_idx;
table->DrawSplitter = &table->TempData->DrawSplitter;
table->DrawSplitter->Clear();
@ -1382,9 +1381,8 @@ void ImGui::EndTable()
// Clear or restore current table, if any
IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table);
IM_ASSERT(g.CurrentTableStackIdx >= 0);
g.CurrentTableStackIdx--;
temp_data = g.CurrentTableStackIdx >= 0 ? &g.TablesTempDataStack[g.CurrentTableStackIdx] : NULL;
IM_ASSERT(g.TablesTempDataStacked > 0);
temp_data = (--g.TablesTempDataStacked > 0) ? &g.TablesTempData[g.TablesTempDataStacked - 1] : NULL;
g.CurrentTable = temp_data ? g.Tables.GetByIndex(temp_data->TableIndex) : NULL;
if (g.CurrentTable)
{

View File

@ -1,4 +1,4 @@
// dear imgui, v1.85
// dear imgui, v1.86
// (widgets code)
/*
@ -564,7 +564,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
SetFocusID(id, window);
FocusWindow(window);
}
if ((flags & ImGuiButtonFlags_PressedOnClick) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[mouse_button_clicked]))
if ((flags & ImGuiButtonFlags_PressedOnClick) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseClickedCount[mouse_button_clicked] == 2))
{
pressed = true;
if (flags & ImGuiButtonFlags_NoHoldingActiveId)
@ -641,7 +641,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
if ((release_in || release_anywhere) && !g.DragDropActive)
{
// Report as pressed when releasing the mouse (this is the most common path)
bool is_double_click_release = (flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDownWasDoubleClick[mouse_button];
bool is_double_click_release = (flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseReleased[mouse_button] && g.IO.MouseClickedLastCount[mouse_button] == 2;
bool is_repeating_already = (flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[mouse_button] >= g.IO.KeyRepeatDelay; // Repeat mode trumps <on release>
if (!is_double_click_release && !is_repeating_already)
pressed = true;
@ -896,7 +896,9 @@ void ImGui::Scrollbar(ImGuiAxis axis)
}
float size_avail = window->InnerRect.Max[axis] - window->InnerRect.Min[axis];
float size_contents = window->ContentSize[axis] + window->WindowPadding[axis] * 2.0f;
ScrollbarEx(bb, id, axis, &window->Scroll[axis], size_avail, size_contents, rounding_corners);
ImS64 scroll = (ImS64)window->Scroll[axis];
ScrollbarEx(bb, id, axis, &scroll, (ImS64)size_avail, (ImS64)size_contents, rounding_corners);
window->Scroll[axis] = (float)scroll;
}
// Vertical/Horizontal scrollbar
@ -905,7 +907,7 @@ void ImGui::Scrollbar(ImGuiAxis axis)
// - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar
// - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal.
// Still, the code should probably be made simpler..
bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float size_avail_v, float size_contents_v, ImDrawFlags flags)
bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS64* p_scroll_v, ImS64 size_avail_v, ImS64 size_contents_v, ImDrawFlags flags)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
@ -936,8 +938,8 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa
// Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount)
// But we maintain a minimum size in pixel to allow for the user to still aim inside.
IM_ASSERT(ImMax(size_contents_v, size_avail_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers.
const float win_size_v = ImMax(ImMax(size_contents_v, size_avail_v), 1.0f);
const float grab_h_pixels = ImClamp(scrollbar_size_v * (size_avail_v / win_size_v), style.GrabMinSize, scrollbar_size_v);
const ImS64 win_size_v = ImMax(ImMax(size_contents_v, size_avail_v), (ImS64)1);
const float grab_h_pixels = ImClamp(scrollbar_size_v * ((float)size_avail_v / (float)win_size_v), style.GrabMinSize, scrollbar_size_v);
const float grab_h_norm = grab_h_pixels / scrollbar_size_v;
// Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar().
@ -945,13 +947,13 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa
bool hovered = false;
ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus);
float scroll_max = ImMax(1.0f, size_contents_v - size_avail_v);
float scroll_ratio = ImSaturate(*p_scroll_v / scroll_max);
const ImS64 scroll_max = ImMax((ImS64)1, size_contents_v - size_avail_v);
float scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max);
float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; // Grab position in normalized space
if (held && allow_interaction && grab_h_norm < 1.0f)
{
float scrollbar_pos_v = bb.Min[axis];
float mouse_pos_v = g.IO.MousePos[axis];
const float scrollbar_pos_v = bb.Min[axis];
const float mouse_pos_v = g.IO.MousePos[axis];
// Click position in scrollbar normalized space (0.0f->1.0f)
const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v);
@ -971,10 +973,10 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa
// Apply scroll (p_scroll_v will generally point on one member of window->Scroll)
// It is ok to modify Scroll here because we are being called in Begin() after the calculation of ContentSize and before setting up our starting position
const float scroll_v_norm = ImSaturate((clicked_v_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm * 0.5f) / (1.0f - grab_h_norm));
*p_scroll_v = IM_ROUND(scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v));
*p_scroll_v = (ImS64)(scroll_v_norm * scroll_max);
// Update values for rendering
scroll_ratio = ImSaturate(*p_scroll_v / scroll_max);
scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max);
grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
// Update distance to grab now that we have seeked and saturated
@ -1391,11 +1393,20 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
if (g.GroupStack.Size > 0 && g.GroupStack.back().WindowID == window->ID)
x1 += window->DC.Indent.x;
// FIXME-WORKRECT: In theory we should simply be using WorkRect.Min.x/Max.x everywhere but it isn't aesthetically what we want,
// need to introduce a variant of WorkRect for that purpose. (#4787)
if (ImGuiTable* table = g.CurrentTable)
{
x1 = table->Columns[table->CurrentColumn].MinX;
x2 = table->Columns[table->CurrentColumn].MaxX;
}
ImGuiOldColumns* columns = (flags & ImGuiSeparatorFlags_SpanAllColumns) ? window->DC.CurrentColumns : NULL;
if (columns)
PushColumnsBackground();
// We don't provide our width to the layout so that it doesn't get feed back into AutoFit
// FIXME: This prevents ->CursorMaxPos based bounding box evaluation from working (e.g. TableEndCell)
const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness_draw));
ItemSize(ImVec2(0.0f, thickness_layout));
const bool item_visible = ItemAdd(bb, 0);
@ -1424,7 +1435,7 @@ void ImGui::Separator()
// Those flags should eventually be overridable by the user
ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal;
flags |= ImGuiSeparatorFlags_SpanAllColumns;
flags |= ImGuiSeparatorFlags_SpanAllColumns; // NB: this only applies to legacy Columns() api as they relied on Separator() a lot.
SeparatorEx(flags);
}
@ -2409,7 +2420,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
{
const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
const bool clicked = (hovered && g.IO.MouseClicked[0]);
const bool double_clicked = (hovered && g.IO.MouseDoubleClicked[0]);
const bool double_clicked = (hovered && g.IO.MouseClickedCount[0] == 2);
if (input_requested_by_tabbing || clicked || double_clicked || g.NavActivateId == id || g.NavActivateInputId == id)
{
SetActiveID(id, window);
@ -3679,17 +3690,18 @@ static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* ob
}
// When ImGuiInputTextFlags_Password is set, we don't want actions such as CTRL+Arrow to leak the fact that underlying data are blanks or separators.
static bool is_separator(unsigned int c) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
static bool is_separator(unsigned int c) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|' || c=='\n' || c=='\r'; }
static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (is_separator(obj->TextW[idx - 1]) && !is_separator(obj->TextW[idx]) ) : 1; }
static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (!is_separator(obj->TextW[idx - 1]) && is_separator(obj->TextW[idx])) : 1; }
static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
#ifdef __APPLE__ // FIXME: Move setting to IO structure
static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (!is_separator(obj->TextW[idx - 1]) && is_separator(obj->TextW[idx]) ) : 1; }
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
#else
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
#endif
static int STB_TEXTEDIT_MOVEWORDRIGHT_MAC(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
#define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h
#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_IMPL
#ifdef __APPLE__ // FIXME: Move setting to IO structure
#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_MAC
#else
static int STB_TEXTEDIT_MOVEWORDRIGHT_WIN(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_WIN
#endif
static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
{
@ -3881,11 +3893,12 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f
// Generic named filters
if (apply_named_filters && (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific)))
{
// The libc allows overriding locale, with e.g. 'setlocale(LC_NUMERIC, "de_DE.UTF-8");' which affect the output/input of printf/scanf.
// The libc allows overriding locale, with e.g. 'setlocale(LC_NUMERIC, "de_DE.UTF-8");' which affect the output/input of printf/scanf to use e.g. ',' instead of '.'.
// The standard mandate that programs starts in the "C" locale where the decimal point is '.'.
// We don't really intend to provide widespread support for it, but out of empathy for people stuck with using odd API, we support the bare minimum aka overriding the decimal point.
// Change the default decimal_point with:
// ImGui::GetCurrentContext()->PlatformLocaleDecimalPoint = *localeconv()->decimal_point;
// Users of non-default decimal point (in particular ',') may be affected by word-selection logic (is_word_boundary_from_right/is_word_boundary_from_left) functions.
ImGuiContext& g = *GImGui;
const unsigned c_decimal_point = (unsigned int)g.PlatformLocaleDecimalPoint;
@ -3964,7 +3977,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (is_resizable)
IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag!
if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope,
if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope (including the scrollbar)
BeginGroup();
const ImGuiID id = window->GetID(label);
const ImVec2 label_size = CalcTextSize(label, NULL, true);
@ -3977,6 +3990,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
ImGuiWindow* draw_window = window;
ImVec2 inner_size = frame_size;
ImGuiItemStatusFlags item_status_flags = 0;
ImGuiLastItemData item_data_backup;
if (is_multiline)
{
ImVec2 backup_pos = window->DC.CursorPos;
@ -3987,6 +4001,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
return false;
}
item_status_flags = g.LastItemData.StatusFlags;
item_data_backup = g.LastItemData;
window->DC.CursorPos = backup_pos;
// We reproduce the contents of BeginChildFrame() in order to provide 'label' so our window internal data are easier to read/debug.
@ -3994,8 +4009,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]);
PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding);
PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize);
PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); // Ensure no clip rect so mouse hover can reach FramePadding edges
bool child_visible = BeginChildEx(label, id, frame_bb.GetSize(), true, ImGuiWindowFlags_NoMove);
PopStyleVar(2);
PopStyleVar(3);
PopStyleColor();
if (!child_visible)
{
@ -4163,8 +4179,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
state->Edited = false;
state->BufCapacityA = buf_size;
state->Flags = flags;
state->UserCallback = callback;
state->UserCallbackData = callback_user_data;
// Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
// Down the line we should have a cleaner library-wide concept of Selected vs Active.
@ -4176,19 +4190,49 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y) : (g.FontSize * 0.5f));
const bool is_osx = io.ConfigMacOSXBehaviors;
if (select_all || (hovered && !is_osx && io.MouseDoubleClicked[0]))
if (select_all)
{
state->SelectAll();
state->SelectedAllMouseLock = true;
}
else if (hovered && is_osx && io.MouseDoubleClicked[0])
else if (hovered && io.MouseClickedCount[0] >= 2 && !io.KeyShift)
{
// Double-click select a word only, OS X style (by simulating keystrokes)
state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT);
state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT);
stb_textedit_click(state, &state->Stb, mouse_x, mouse_y);
const int multiclick_count = (io.MouseClickedCount[0] - 2);
if ((multiclick_count % 2) == 0)
{
// Double-click: Select word
// We always use the "Mac" word advance for double-click select vs CTRL+Right which use the platform dependent variant:
// FIXME: There are likely many ways to improve this behavior, but there's no "right" behavior (depends on use-case, software, OS)
const bool is_bol = (state->Stb.cursor == 0) || ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb.cursor - 1) == '\n';
if (STB_TEXT_HAS_SELECTION(&state->Stb) || !is_bol)
state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT);
//state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT);
if (!STB_TEXT_HAS_SELECTION(&state->Stb))
ImStb::stb_textedit_prep_selection_at_cursor(&state->Stb);
state->Stb.cursor = ImStb::STB_TEXTEDIT_MOVEWORDRIGHT_MAC(state, state->Stb.cursor);
state->Stb.select_end = state->Stb.cursor;
ImStb::stb_textedit_clamp(state, &state->Stb);
}
else
{
// Triple-click: Select line
const bool is_eol = ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb.cursor) == '\n';
state->OnKeyPressed(STB_TEXTEDIT_K_LINESTART);
state->OnKeyPressed(STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT);
state->OnKeyPressed(STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT);
if (!is_eol && is_multiline)
{
ImSwap(state->Stb.select_start, state->Stb.select_end);
state->Stb.cursor = state->Stb.select_end;
}
state->CursorFollow = false;
}
state->CursorAnimReset();
}
else if (io.MouseClicked[0] && !state->SelectedAllMouseLock)
{
// FIXME: unselect on late click could be done release?
if (hovered)
{
stb_textedit_click(state, &state->Stb, mouse_x, mouse_y);
@ -4273,7 +4317,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
else if (IsKeyPressedMap(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; }
else if (IsKeyPressedMap(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly && !is_cut) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Backspace) && !is_readonly)
{
if (!state->HasSelection())
@ -4372,11 +4416,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
}
// Process callbacks and apply result back to user's buffer.
const char* apply_new_text = NULL;
int apply_new_text_length = 0;
if (g.ActiveId == id)
{
IM_ASSERT(state != NULL);
const char* apply_new_text = NULL;
int apply_new_text_length = 0;
if (cancel_edit)
{
// Restore initial value. Only return true if restoring to the initial value changes the current buffer contents.
@ -4452,8 +4496,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
callback_data.Flags = flags;
callback_data.UserData = callback_user_data;
char* callback_buf = is_readonly ? buf : state->TextA.Data;
callback_data.EventKey = event_key;
callback_data.Buf = state->TextA.Data;
callback_data.Buf = callback_buf;
callback_data.BufTextLen = state->CurLenA;
callback_data.BufSize = state->BufCapacityA;
callback_data.BufDirty = false;
@ -4468,7 +4513,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
callback(&callback_data);
// Read back what user may have modified
IM_ASSERT(callback_data.Buf == state->TextA.Data); // Invalid to modify those fields
callback_buf = is_readonly ? buf : state->TextA.Data; // Pointer may have been invalidated by a resize callback
IM_ASSERT(callback_data.Buf == callback_buf); // Invalid to modify those fields
IM_ASSERT(callback_data.BufSize == state->BufCapacityA);
IM_ASSERT(callback_data.Flags == flags);
const bool buf_dirty = callback_data.BufDirty;
@ -4495,39 +4541,37 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
}
}
// Copy result to user buffer
if (apply_new_text)
{
// We cannot test for 'backup_current_text_length != apply_new_text_length' here because we have no guarantee that the size
// of our owned buffer matches the size of the string object held by the user, and by design we allow InputText() to be used
// without any storage on user's side.
IM_ASSERT(apply_new_text_length >= 0);
if (is_resizable)
{
ImGuiInputTextCallbackData callback_data;
callback_data.EventFlag = ImGuiInputTextFlags_CallbackResize;
callback_data.Flags = flags;
callback_data.Buf = buf;
callback_data.BufTextLen = apply_new_text_length;
callback_data.BufSize = ImMax(buf_size, apply_new_text_length + 1);
callback_data.UserData = callback_user_data;
callback(&callback_data);
buf = callback_data.Buf;
buf_size = callback_data.BufSize;
apply_new_text_length = ImMin(callback_data.BufTextLen, buf_size - 1);
IM_ASSERT(apply_new_text_length <= buf_size);
}
//IMGUI_DEBUG_LOG("InputText(\"%s\"): apply_new_text length %d\n", label, apply_new_text_length);
// If the underlying buffer resize was denied or not carried to the next frame, apply_new_text_length+1 may be >= buf_size.
ImStrncpy(buf, apply_new_text, ImMin(apply_new_text_length + 1, buf_size));
value_changed = true;
}
// Clear temporary user storage
state->Flags = ImGuiInputTextFlags_None;
state->UserCallback = NULL;
state->UserCallbackData = NULL;
}
// Copy result to user buffer. This can currently only happen when (g.ActiveId == id)
if (apply_new_text != NULL)
{
// We cannot test for 'backup_current_text_length != apply_new_text_length' here because we have no guarantee that the size
// of our owned buffer matches the size of the string object held by the user, and by design we allow InputText() to be used
// without any storage on user's side.
IM_ASSERT(apply_new_text_length >= 0);
if (is_resizable)
{
ImGuiInputTextCallbackData callback_data;
callback_data.EventFlag = ImGuiInputTextFlags_CallbackResize;
callback_data.Flags = flags;
callback_data.Buf = buf;
callback_data.BufTextLen = apply_new_text_length;
callback_data.BufSize = ImMax(buf_size, apply_new_text_length + 1);
callback_data.UserData = callback_user_data;
callback(&callback_data);
buf = callback_data.Buf;
buf_size = callback_data.BufSize;
apply_new_text_length = ImMin(callback_data.BufTextLen, buf_size - 1);
IM_ASSERT(apply_new_text_length <= buf_size);
}
//IMGUI_DEBUG_LOG("InputText(\"%s\"): apply_new_text length %d\n", label, apply_new_text_length);
// If the underlying buffer resize was denied or not carried to the next frame, apply_new_text_length+1 may be >= buf_size.
ImStrncpy(buf, apply_new_text, ImMin(apply_new_text_length + 1, buf_size));
value_changed = true;
}
// Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value)
@ -4649,7 +4693,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Test if cursor is vertically visible
if (cursor_offset.y - g.FontSize < scroll_y)
scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize);
else if (cursor_offset.y - inner_size.y >= scroll_y)
else if (cursor_offset.y - (inner_size.y - style.FramePadding.y * 2.0f) >= scroll_y)
scroll_y = cursor_offset.y - inner_size.y + style.FramePadding.y * 2.0f;
const float scroll_max_y = ImMax((text_size.y + style.FramePadding.y * 2.0f) - inner_size.y, 0.0f);
scroll_y = ImClamp(scroll_y, 0.0f, scroll_max_y);
@ -4741,9 +4785,23 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (is_multiline)
{
// For focus requests to work on our multiline we need to ensure our child ItemAdd() call specifies the ImGuiItemFlags_Inputable (ref issue #4761)...
Dummy(ImVec2(text_size.x, text_size.y + style.FramePadding.y));
ImGuiItemFlags backup_item_flags = g.CurrentItemFlags;
g.CurrentItemFlags |= ImGuiItemFlags_Inputable | ImGuiItemFlags_NoTabStop;
EndChild();
item_data_backup.StatusFlags |= (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredWindow);
g.CurrentItemFlags = backup_item_flags;
// ...and then we need to undo the group overriding last item data, which gets a bit messy as EndGroup() tries to forward scrollbar being active...
// FIXME: This quite messy/tricky, should attempt to get rid of the child window.
EndGroup();
if (g.LastItemData.ID == 0)
{
g.LastItemData.ID = id;
g.LastItemData.InFlags = item_data_backup.InFlags;
g.LastItemData.StatusFlags = item_data_backup.StatusFlags;
}
}
// Log as text
@ -5548,7 +5606,7 @@ void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags
{
ImGuiContext& g = *GImGui;
BeginTooltipEx(0, ImGuiTooltipFlags_OverridePreviousTooltip);
BeginTooltipEx(ImGuiTooltipFlags_OverridePreviousTooltip, ImGuiWindowFlags_None);
const char* text_end = text ? FindRenderedTextEnd(text, NULL) : text;
if (text_end > text)
{
@ -5919,7 +5977,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
toggled = true;
if (flags & ImGuiTreeNodeFlags_OpenOnArrow)
toggled |= is_mouse_x_over_arrow && !g.NavDisableMouseHover; // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job
if ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) && g.IO.MouseDoubleClicked[0])
if ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) && g.IO.MouseClickedCount[0] == 2)
toggled = true;
}
else if (pressed && g.DragDropHoldJustPressedId == id)
@ -6226,7 +6284,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
{
if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
{
SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent, ImRect(bb.Min - window->Pos, bb.Max - window->Pos)); // (bb == NavRect)
SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent, WindowRectAbsToRel(window, bb)); // (bb == NavRect)
g.NavDisableHighlight = true;
}
}
@ -6810,6 +6868,23 @@ void ImGui::EndMainMenuBar()
End();
}
static bool IsRootOfOpenMenuSet()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
if ((g.OpenPopupStack.Size <= g.BeginPopupStack.Size) || (window->Flags & ImGuiWindowFlags_ChildMenu))
return false;
// Initially we used 'OpenParentId' to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) based on parent ID.
// This would however prevent the use of e.g. PuhsID() user code submitting menus.
// Previously this worked between popup and a first child menu because the first child menu always had the _ChildWindow flag,
// making hovering on parent popup possible while first child menu was focused - but this was generally a bug with other side effects.
// Instead we don't treat Popup specifically (in order to consistently support menu features in them), maybe the first child menu of a Popup
// doesn't have the _ChildWindow flag, and we rely on this IsRootOfOpenMenuSet() check to allow hovering between root window/popup and first chilld menu.
const ImGuiPopupData* upper_popup = &g.OpenPopupStack[g.BeginPopupStack.Size];
return (/*upper_popup->OpenParentId == window->IDStack.back() &&*/ upper_popup->Window && (upper_popup->Window->Flags & ImGuiWindowFlags_ChildMenu));
}
bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
{
ImGuiWindow* window = GetCurrentWindow();
@ -6822,8 +6897,9 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
bool menu_is_open = IsPopupOpen(id, ImGuiPopupFlags_None);
// Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu)
// The first menu in a hierarchy isn't so hovering doesn't get accross (otherwise e.g. resizing borders with ImGuiButtonFlags_FlattenChildren would react), but top-most BeginMenu() will bypass that limitation.
ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus;
if (window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu))
if (window->Flags & ImGuiWindowFlags_ChildMenu)
flags |= ImGuiWindowFlags_ChildWindow;
// If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin().
@ -6842,11 +6918,12 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
g.MenusIdSubmittedThisFrame.push_back(id);
ImVec2 label_size = CalcTextSize(label, NULL, true);
bool pressed;
bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].OpenParentId == window->IDStack.back());
// Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent without always being a Child window)
const bool menuset_is_open = IsRootOfOpenMenuSet();
ImGuiWindow* backed_nav_window = g.NavWindow;
if (menuset_is_open)
g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent)
g.NavWindow = window;
// The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu,
// However the final position is going to be different! It is chosen by FindBestWindowPosForPopup().
@ -6856,6 +6933,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
if (!enabled)
BeginDisabled();
const ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
bool pressed;
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
{
// Menu inside an horizontal menu bar
@ -6972,7 +7050,9 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
if (menu_is_open)
{
SetNextWindowPos(popup_pos, ImGuiCond_Always); // Note: this is super misleading! The value will serve as reference for FindBestWindowPosForPopup(), not actual pos.
PushStyleVar(ImGuiStyleVar_ChildRounding, style.PopupRounding); // First level will use _PopupRounding, subsequent will use _ChildRounding
menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
PopStyleVar();
}
else
{
@ -7015,13 +7095,19 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
ImVec2 pos = window->DC.CursorPos;
ImVec2 label_size = CalcTextSize(label, NULL, true);
const bool menuset_is_open = IsRootOfOpenMenuSet();
ImGuiWindow* backed_nav_window = g.NavWindow;
if (menuset_is_open)
g.NavWindow = window;
// We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73),
// but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only.
bool pressed;
PushID(label);
if (!enabled)
BeginDisabled();
const ImGuiSelectableFlags flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover;
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover;
const ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
{
@ -7031,7 +7117,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f);
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
pressed = Selectable("", selected, flags, ImVec2(w, 0.0f));
pressed = Selectable("", selected, selectable_flags, ImVec2(w, 0.0f));
PopStyleVar();
RenderText(text_pos, label);
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
@ -7046,7 +7132,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
float checkmark_w = IM_FLOOR(g.FontSize * 1.20f);
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame
float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
pressed = Selectable("", false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label);
if (icon_w > 0.0f)
RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon);
@ -7063,6 +7149,8 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
if (!enabled)
EndDisabled();
PopID();
if (menuset_is_open)
g.NavWindow = backed_nav_window;
return pressed;
}
@ -7205,8 +7293,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
// Ensure correct ordering when toggling ImGuiTabBarFlags_Reorderable flag, or when a new tab was added while being not reorderable
if ((flags & ImGuiTabBarFlags_Reorderable) != (tab_bar->Flags & ImGuiTabBarFlags_Reorderable) || (tab_bar->TabsAddedNew && !(flags & ImGuiTabBarFlags_Reorderable)))
if (tab_bar->Tabs.Size > 1)
ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByBeginOrder);
ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByBeginOrder);
tab_bar->TabsAddedNew = false;
// Flags

View File

@ -226,6 +226,12 @@ namespace
uint32_t glyph_index = FT_Get_Char_Index(Face, codepoint);
if (glyph_index == 0)
return NULL;
// If this crash for you: FreeType 2.11.0 has a crash bug on some bitmap/colored fonts.
// - https://gitlab.freedesktop.org/freetype/freetype/-/issues/1076
// - https://github.com/ocornut/imgui/issues/4567
// - https://github.com/ocornut/imgui/issues/4566
// You can use FreeType 2.10, or the patched version of 2.11.0 in VcPkg, or probably any upcoming FreeType version.
FT_Error error = FT_Load_Glyph(Face, glyph_index, LoadFlags);
if (error)
return NULL;