From edc66d79c7df44899cb1e9be4f839ef4371be91b Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 21 Feb 2025 23:09:54 +0100 Subject: [PATCH 01/15] Nav: extract code into a NavUpdateWindowingApplyFocus() so it may be reused elsewhere. --- imgui.cpp | 50 +++++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 501a19c66..9e2a5e200 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1212,6 +1212,7 @@ static void UpdateWindowInFocusOrderList(ImGuiWindow* window, bool j // Navigation static void NavUpdate(); static void NavUpdateWindowing(); +static void NavUpdateWindowingApplyFocus(ImGuiWindow* window); static void NavUpdateWindowingOverlay(); static void NavUpdateCancelRequest(); static void NavUpdateCreateMoveRequest(); @@ -13651,6 +13652,33 @@ static void NavUpdateWindowingTarget(int focus_change_dir) g.NavWindowingToggleLayer = false; } +// Apply focus and close overlay +static void ImGui::NavUpdateWindowingApplyFocus(ImGuiWindow* apply_focus_window) +{ + ImGuiContext& g = *GImGui; + if (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindow) + { + ClearActiveID(); + SetNavCursorVisibleAfterMove(); + ClosePopupsOverWindow(apply_focus_window, false); + FocusWindow(apply_focus_window, ImGuiFocusRequestFlags_RestoreFocusedChild); + apply_focus_window = g.NavWindow; + if (apply_focus_window->NavLastIds[0] == 0) + NavInitWindow(apply_focus_window, false); + + // If the window has ONLY a menu layer (no main layer), select it directly + // Use NavLayersActiveMaskNext since windows didn't have a chance to be Begin()-ed on this frame, + // so CTRL+Tab where the keys are only held for 1 frame will be able to use correct layers mask since + // the target window as already been previewed once. + // FIXME-NAV: This should be done in NavInit.. or in FocusWindow... However in both of those cases, + // we won't have a guarantee that windows has been visible before and therefore NavLayersActiveMask* + // won't be valid. + if (apply_focus_window->DC.NavLayersActiveMaskNext == (1 << ImGuiNavLayer_Menu)) + g.NavLayer = ImGuiNavLayer_Menu; + } + g.NavWindowingTarget = NULL; +} + // Windowing management mode // Keyboard: CTRL+Tab (change focus/move/resize), Alt (toggle menu layer) // Gamepad: Hold Menu/Square (change focus/move/resize), Tap Menu/Square (toggle menu layer) @@ -13802,28 +13830,8 @@ static void ImGui::NavUpdateWindowing() } // Apply final focus - if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindow)) - { - ClearActiveID(); - SetNavCursorVisibleAfterMove(); - ClosePopupsOverWindow(apply_focus_window, false); - FocusWindow(apply_focus_window, ImGuiFocusRequestFlags_RestoreFocusedChild); - apply_focus_window = g.NavWindow; - if (apply_focus_window->NavLastIds[0] == 0) - NavInitWindow(apply_focus_window, false); - - // If the window has ONLY a menu layer (no main layer), select it directly - // Use NavLayersActiveMaskNext since windows didn't have a chance to be Begin()-ed on this frame, - // so CTRL+Tab where the keys are only held for 1 frame will be able to use correct layers mask since - // the target window as already been previewed once. - // FIXME-NAV: This should be done in NavInit.. or in FocusWindow... However in both of those cases, - // we won't have a guarantee that windows has been visible before and therefore NavLayersActiveMask* - // won't be valid. - if (apply_focus_window->DC.NavLayersActiveMaskNext == (1 << ImGuiNavLayer_Menu)) - g.NavLayer = ImGuiNavLayer_Menu; - } if (apply_focus_window) - g.NavWindowingTarget = NULL; + NavUpdateWindowingApplyFocus(apply_focus_window); // Apply menu/layer toggle if (apply_toggle_layer && g.NavWindow) From 74afea04d6432e3cbcadd43f8eaf771aed48a1c8 Mon Sep 17 00:00:00 2001 From: Tygyh <32486062+tygyh@users.noreply.github.com> Date: Sat, 22 Feb 2025 23:36:40 +0100 Subject: [PATCH 02/15] Fix typos in docs (#8427) --- docs/CHANGELOG.txt | 4 ++-- docs/CONTRIBUTING.md | 2 +- docs/TODO.txt | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 044be4360..0d1bbd052 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -346,7 +346,7 @@ Other changes: initial mouse down event. - Note that it may reveal incorrect usage if you were using InputInt/InputFloat without persistent storage by relying solely on e.g. IsItemDeactivatedAfterEdit(): - this was never supported and didn't work consistantly (see #8149). + this was never supported and didn't work consistently (see #8149). - InputText: fixed a bug (regression in 1.91.2) where modifying text buffer within a callback would sometimes prevents further appending to the buffer. - Tabs, Style: made ImGuiCol_TabDimmedSelectedOverline alpha 0 (not visible) in default @@ -450,7 +450,7 @@ Other changes: supported by InputFloat, InputInt, InputScalar etc. widgets. It actually never was. (#8065, #3946) - imgui_freetype: Added support for plutosvg (as an alternative to lunasvg) to render OpenType SVG fonts. Requires defining IMGUI_ENABLE_FREETYPE_PLUTOSVG along with IMGUI_ENABLE_FREETYPE. - Providing headers/librairies for plutosvg + plutovg is up to you (see #7927 for help). + Providing headers/libraries for plutosvg + plutovg is up to you (see #7927 for help). (#7927, #7187, #6591, #6607) [@pthom] - Backends: DX11, DX12, SDLRenderer2/3. Vulkan, WGPU: expose selected state in ImGui_ImplXXXX_RenderState structures during render loop user draw callbacks. diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index f70cf0e23..fb946c4b3 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -77,5 +77,5 @@ If you have been using Dear ImGui for a while or have been using C/C++ for sever Any code you submit will become part of the repository and be distributed under the [Dear ImGui license](https://github.com/ocornut/imgui/blob/master/LICENSE.txt). By submitting code to the project you agree that the code is your work and that you can give it to the project. -You also agree by submitting your code that you grant all transferrable rights to the code to the project maintainer, including for example re-licensing the code, modifying the code, and distributing it in source or binary forms. Specifically, this includes a requirement that you assign copyright to the project maintainer. For this reason, do not modify any copyright statements in files in any PRs. +You also agree by submitting your code that you grant all transferable rights to the code to the project maintainer, including for example re-licensing the code, modifying the code, and distributing it in source or binary forms. Specifically, this includes a requirement that you assign copyright to the project maintainer. For this reason, do not modify any copyright statements in files in any PRs. diff --git a/docs/TODO.txt b/docs/TODO.txt index 31238ff83..14a152a4b 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -22,7 +22,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - window: using SetWindowPos() inside Begin() and moving the window with the mouse reacts a very ugly glitch. We should just defer the SetWindowPos() call. - window: GetWindowSize() returns (0,0) when not calculated? (#1045) - window: investigate better auto-positioning for new windows. - - window: top most window flag? more z-order contrl? (#2574) + - window: top most window flag? more z-order control? (#2574) - window/size: manually triggered auto-fit (double-click on grip) shouldn't resize window down to viewport size? - window/size: how to allow to e.g. auto-size vertically to fit contents, but be horizontally resizable? Assuming SetNextWindowSize() is modified to treat -1.0f on each axis as "keep as-is" (would be good but might break erroneous code): Problem is UpdateWindowManualResize() and lots of code treat (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) together. - window/opt: freeze window flag: if not focused/hovered, return false, render with previous ImDrawList. and/or reduce refresh rate. -> this may require enforcing that it is illegal to submit contents if Begin returns false. @@ -57,7 +57,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - widgets: start exposing PushItemFlag() and ImGuiItemFlags - widgets: alignment options in style (e.g. center Selectable, Right-Align within Button, etc.) #1260 - widgets: activate by identifier (trigger button, focus given id) - - widgets: custom glyph/shapes replacements for stock sapes. (also #6090 #2431 #2235 #6517) + - widgets: custom glyph/shapes replacements for stock shapes. (also #6090 #2431 #2235 #6517) - widgets: coloredit: keep reporting as active when picker is on? - widgets: group/scalarn functions: expose more per-component information. e.g. store NextItemData.ComponentIdx set by scalarn function, groups can expose them back somehow. - selectable: using (size.x == 0.0f) and (SelectableTextAlign.x > 0.0f) followed by SameLine() is currently not supported. @@ -137,7 +137,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - image/image button: misalignment on padded/bordered button? - image/image button: parameters are confusing, image() has tint_col,border_col whereas imagebutton() has bg_col/tint_col. Even thou they are different parameters ordering could be more consistent. can we fix that? - slider: allow using the [-]/[+] buttons used by InputFloat()/InputInt() - - slider: add dragging-based widgets to edit values with mouse (on 2 axises), saving screen real-estate. + - slider: add dragging-based widgets to edit values with mouse (on 2 axes), saving screen real-estate. - slider: tint background based on value (e.g. v_min -> v_max, or use 0.0f either side of the sign) - slider: relative dragging? + precision dragging - slider: step option (#1183) @@ -213,7 +213,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - log: let user copy any window content to clipboard easily (CTRL+C on windows? while moving it? context menu?). code is commented because it fails with multiple Begin/End pairs. - log: obsolete LogButtons().... (was: LogButtons() options for specifying depth and/or hiding depth slider) - - filters: set a current filter that certains items (e.g. tree node) can automatically query to hide themselves + - filters: set a current filter that certain items (e.g. tree node) can automatically query to hide themselves - filters: handle wild-cards (with implicit leading/trailing *), reg-exprs - filters: fuzzy matches (may use code at blog.forrestthewoods.com/4cffeed33fdb) From 5dce79e9410bfe0fd1709980b637ce38a2313ed0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 24 Feb 2025 10:52:15 +0100 Subject: [PATCH 03/15] Backends: DirectX12: Fixed an issue where pre-1.91.5 legacy ImGui_ImplDX12_Init() signature started breaking in 1.91.8 due to missing command queue. (#8429) --- backends/imgui_impl_dx12.cpp | 25 ++++++++++++++++++++++--- backends/imgui_impl_dx12.h | 5 +++-- docs/CHANGELOG.txt | 2 ++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 6f17f587a..8449832c5 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -19,6 +19,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-24: DirectX12: Fixed an issue where ImGui_ImplDX12_Init() signature change from 2024-11-15 combined with change from 2025-01-15 made legacy ImGui_ImplDX12_Init() crash. (#8429) // 2025-01-15: DirectX12: Texture upload use the command queue provided in ImGui_ImplDX12_InitInfo instead of creating its own. // 2024-12-09: DirectX12: Let user specifies the DepthStencilView format by setting ImGui_ImplDX12_InitInfo::DSVFormat. // 2024-11-15: DirectX12: *BREAKING CHANGE* Changed ImGui_ImplDX12_Init() signature to take a ImGui_ImplDX12_InitInfo struct. Legacy ImGui_ImplDX12_Init() signature is still supported (will obsolete). @@ -75,6 +76,8 @@ struct ImGui_ImplDX12_Data ID3D12Device* pd3dDevice; ID3D12RootSignature* pRootSignature; ID3D12PipelineState* pPipelineState; + ID3D12CommandQueue* pCommandQueue; + bool commandQueueOwned; DXGI_FORMAT RTVFormat; DXGI_FORMAT DSVFormat; ID3D12DescriptorHeap* pd3dSrvDescHeap; @@ -430,7 +433,7 @@ static void ImGui_ImplDX12_CreateFontsTexture() hr = cmdList->Close(); IM_ASSERT(SUCCEEDED(hr)); - ID3D12CommandQueue* cmdQueue = bd->InitInfo.CommandQueue; + ID3D12CommandQueue* cmdQueue = bd->pCommandQueue; cmdQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&cmdList); hr = cmdQueue->Signal(fence, 1); IM_ASSERT(SUCCEEDED(hr)); @@ -702,6 +705,9 @@ void ImGui_ImplDX12_InvalidateDeviceObjects() if (!bd || !bd->pd3dDevice) return; + if (bd->commandQueueOwned) + SafeRelease(bd->pCommandQueue); + bd->commandQueueOwned = false; SafeRelease(bd->pRootSignature); SafeRelease(bd->pPipelineState); @@ -732,6 +738,8 @@ bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* init_info) init_info = &bd->InitInfo; bd->pd3dDevice = init_info->Device; + IM_ASSERT(init_info->CommandQueue != NULL); + bd->pCommandQueue = init_info->CommandQueue; bd->RTVFormat = init_info->RTVFormat; bd->DSVFormat = init_info->DSVFormat; bd->numFramesInFlight = init_info->NumFramesInFlight; @@ -793,8 +801,19 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO init_info.RTVFormat = rtv_format; init_info.SrvDescriptorHeap = srv_descriptor_heap; init_info.LegacySingleSrvCpuDescriptor = font_srv_cpu_desc_handle; - init_info.LegacySingleSrvGpuDescriptor = font_srv_gpu_desc_handle;; - return ImGui_ImplDX12_Init(&init_info); + init_info.LegacySingleSrvGpuDescriptor = font_srv_gpu_desc_handle; + + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.NodeMask = 1; + HRESULT hr = device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&init_info.CommandQueue)); + IM_ASSERT(SUCCEEDED(hr)); + + bool ret = ImGui_ImplDX12_Init(&init_info); + ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); + bd->commandQueueOwned = true; + return ret; } #endif diff --git a/backends/imgui_impl_dx12.h b/backends/imgui_impl_dx12.h index a57c1694d..736e9f5c2 100644 --- a/backends/imgui_impl_dx12.h +++ b/backends/imgui_impl_dx12.h @@ -27,7 +27,7 @@ struct ImGui_ImplDX12_InitInfo { ID3D12Device* Device; - ID3D12CommandQueue* CommandQueue; + ID3D12CommandQueue* CommandQueue; // Command queue used for queuing texture uploads. int NumFramesInFlight; DXGI_FORMAT RTVFormat; // RenderTarget format. DXGI_FORMAT DSVFormat; // DepthStencilView format. @@ -54,7 +54,8 @@ IMGUI_IMPL_API void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // Legacy initialization API Obsoleted in 1.91.5 -// font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture, they must be in 'srv_descriptor_heap' +// - font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture, they must be in 'srv_descriptor_heap' +// - When we introduced the ImGui_ImplDX12_InitInfo struct we also added a 'ID3D12CommandQueue* CommandQueue' field. IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* srv_descriptor_heap, D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle); #endif diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0d1bbd052..ae0963703 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -93,6 +93,8 @@ Other changes: and ImGuiMouseCursor_Progress cursors. - Backends: OpenGL3: Lazily reinitialize embedded GL loader for when calling backend from e.g. other DLL boundaries. (#8406) +- Backends: DirectX12: Fixed an issue where pre-1.91.5 legacy ImGui_ImplDX12_Init() + signature started breaking in 1.91.8 due to missing command queue. (#8429) - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] - Backends: Vulkan: Added ApiVersion field in ImGui_ImplVulkan_InitInfo. Default to header version if unspecified. (#8326, #8365) [@mklefrancois] From ef969a53f5fe8b956dc252718f14997393e3344f Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 24 Feb 2025 11:44:48 +0100 Subject: [PATCH 04/15] Tabs: fixed Unsaved Marker not being visible when Close Button is. (#8430, #8387) --- imgui_widgets.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 6e08cec22..f011805f9 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -10377,9 +10377,15 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, else close_button_visible = (g.Style.TabCloseButtonMinWidthUnselected < 0.0f) ? true : (is_hovered && bb.GetWidth() >= ImMax(button_sz, g.Style.TabCloseButtonMinWidthUnselected)); } - bool unsaved_marker_visible = (flags & ImGuiTabItemFlags_UnsavedDocument) != 0 && (button_pos.x + button_sz <= bb.Max.x); - if (close_button_visible) + // When tabs/document is unsaved, the unsaved marker takes priority over the close button. + const bool unsaved_marker_visible = (flags & ImGuiTabItemFlags_UnsavedDocument) != 0 && (button_pos.x + button_sz <= bb.Max.x) && (!close_button_visible || !is_hovered); + if (unsaved_marker_visible) + { + const ImRect bullet_bb(button_pos, button_pos + ImVec2(button_sz, button_sz)); + RenderBullet(draw_list, bullet_bb.GetCenter(), GetColorU32(ImGuiCol_Text)); + } + else if (close_button_visible) { ImGuiLastItemData last_item_backup = g.LastItemData; if (CloseButton(close_button_id, button_pos)) @@ -10390,11 +10396,6 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, if (is_hovered && !(flags & ImGuiTabItemFlags_NoCloseWithMiddleMouseButton) && IsMouseClicked(2)) close_button_pressed = true; } - else if (unsaved_marker_visible) - { - const ImRect bullet_bb(button_pos, button_pos + ImVec2(button_sz, button_sz)); - RenderBullet(draw_list, bullet_bb.GetCenter(), GetColorU32(ImGuiCol_Text)); - } // This is all rather complicated // (the main idea is that because the close button only appears on hover, we don't want it to alter the ellipsis position) From dac40d04872e32399f81b1bf8d0befe87c4cd647 Mon Sep 17 00:00:00 2001 From: TheMode Date: Sat, 22 Feb 2025 11:36:41 +0100 Subject: [PATCH 05/15] Backends: SDL2, SDL3: don't call SDL_GetGlobalMouseState() when mouse position is in relative mode. (#8425, #8407) --- backends/imgui_impl_sdl2.cpp | 5 ++++- backends/imgui_impl_sdl3.cpp | 4 +++- docs/CHANGELOG.txt | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index fbfa2fba8..361fc3b57 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-24: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode. // 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. // 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. // 2025-01-20: Made ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode_Manual) accept an empty array. @@ -622,8 +623,10 @@ static void ImGui_ImplSDL2_UpdateMouseData() SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y); // (Optional) Fallback to provide mouse position when focused (SDL_MOUSEMOTION already provides this when hovered or captured) - if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0) + const bool is_relative_mouse_mode = SDL_GetRelativeMouseMode() != 0; + if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode) { + // Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window) int window_x, window_y, mouse_x_global, mouse_y_global; SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global); SDL_GetWindowPosition(bd->Window, &window_x, &window_y); diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 006316afb..d2433793e 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-24: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode. // 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. // 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. // 2025-01-20: Made ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode_Manual) accept an empty array. @@ -588,7 +589,8 @@ static void ImGui_ImplSDL3_UpdateMouseData() SDL_WarpMouseInWindow(bd->Window, io.MousePos.x, io.MousePos.y); // (Optional) Fallback to provide mouse position when focused (SDL_EVENT_MOUSE_MOTION already provides this when hovered or captured) - if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0) + const bool is_relative_mouse_mode = SDL_GetWindowRelativeMouseMode(bd->Window); + if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode) { // Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window) float mouse_x_global, mouse_y_global; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ae0963703..d0acdcb92 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -87,10 +87,12 @@ Other changes: (busy/wait/hourglass shape, with or without an arrow cursor). - Demo: Combos: demonstrate a very simple way to add a filter to a combo, by showing the filter inside the combo contents. (#718) -- Backends: SDL2, SDL3: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn +- Backends: SDL2, SDL3: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. (#7660) [@achabense] - Backends: SDL2, SDL3, Win32, Allegro5: Added support for ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors. +- Backends: SDL2, SDL3: Avoid calling SDL_GetGlobalMouseState() when mouse is in + relative mode. (#8425, #8407) [@TheMode] - Backends: OpenGL3: Lazily reinitialize embedded GL loader for when calling backend from e.g. other DLL boundaries. (#8406) - Backends: DirectX12: Fixed an issue where pre-1.91.5 legacy ImGui_ImplDX12_Init() From 030746faff4a0181ec3149b8457f7bd0a5770819 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 24 Feb 2025 17:45:16 +0100 Subject: [PATCH 06/15] Debug Tools: Added io.ConfigDebugHighlightIdConflictsShowItemPicker. (#7961, #7669) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 24 +++++++++++++++++------- imgui.h | 3 ++- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d0acdcb92..d5c4ded32 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -83,6 +83,8 @@ Other changes: is hovered, merely it's visibility. (#8399, #8387) [@nicovanbentum] - TextLinkOpenURL(): fixed default Win32 io.PlatformOpenInShellFn handler to handle UTF-8 regardless of system regional settings. (#7660) [@achabense] +- Debug Tools: Added io.ConfigDebugHighlightIdConflictsShowItemPicker (defaults to true) + to allow disabled Item Picker suggestion in user facing builds. (#7961, #7669) - Misc: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursors (busy/wait/hourglass shape, with or without an arrow cursor). - Demo: Combos: demonstrate a very simple way to add a filter to a combo, diff --git a/imgui.cpp b/imgui.cpp index 9e2a5e200..a5d52d415 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1454,6 +1454,7 @@ ImGuiIO::ImGuiIO() ConfigMemoryCompactTimer = 60.0f; ConfigDebugIsDebuggerPresent = false; ConfigDebugHighlightIdConflicts = true; + ConfigDebugHighlightIdConflictsShowItemPicker = true; ConfigDebugBeginReturnValueOnce = false; ConfigDebugBeginReturnValueLoop = false; @@ -10445,15 +10446,24 @@ void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip() //BulletText("Code intending to use duplicate ID may use e.g. PushItemFlag(ImGuiItemFlags_AllowDuplicateId, true); ... PopItemFlag()"); // Not making this too visible for fear of it being abused. BulletText("Set io.ConfigDebugHighlightIdConflicts=false to disable this warning in non-programmers builds."); Separator(); - Text("(Hold CTRL to: use"); - SameLine(); - if (SmallButton("Item Picker")) - DebugStartItemPicker(); - SameLine(); - Text("to break in item call-stack, or"); - SameLine(); + if (g.IO.ConfigDebugHighlightIdConflictsShowItemPicker) + { + Text("(Hold CTRL to: use "); + SameLine(0.0f, 0.0f); + if (SmallButton("Item Picker")) + DebugStartItemPicker(); + SameLine(0.0f, 0.0f); + Text(" to break in item call-stack, or "); + } + else + { + Text("(Hold CTRL to "); + } + SameLine(0.0f, 0.0f); if (SmallButton("Open FAQ->About ID Stack System") && g.PlatformIO.Platform_OpenInShellFn != NULL) g.PlatformIO.Platform_OpenInShellFn(&g, "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage"); + SameLine(0.0f, 0.0f); + Text(")"); EndErrorTooltip(); } diff --git a/imgui.h b/imgui.h index a607a669e..5cba09f1c 100644 --- a/imgui.h +++ b/imgui.h @@ -2319,7 +2319,8 @@ struct ImGuiIO // - Code should use PushID()/PopID() in loops, or append "##xx" to same-label identifiers. // - Empty label e.g. Button("") == same ID as parent widget/node. Use Button("##xx") instead! // - See FAQ https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-about-the-id-stack-system - bool ConfigDebugHighlightIdConflicts;// = true // Highlight and show an error message when multiple items have conflicting identifiers. + bool ConfigDebugHighlightIdConflicts;// = true // Highlight and show an error message popup when multiple items have conflicting identifiers. + bool ConfigDebugHighlightIdConflictsShowItemPicker;//=true // Show "Item Picker" button in aforementioned popup. // Tools to test correct Begin/End and BeginChild/EndChild behaviors. // - Presently Begin()/End() and BeginChild()/EndChild() needs to ALWAYS be called in tandem, regardless of return value of BeginXXX() From 6e29450f76db356ebee19a9ac4ee8f4fc129e961 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 25 Feb 2025 16:02:10 +0100 Subject: [PATCH 07/15] Internals: added IsItemActiveAsInputText() helper. --- imgui_internal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui_internal.h b/imgui_internal.h index 22d035423..c4ec9cc93 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3481,6 +3481,7 @@ namespace ImGui inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputId == id); } inline ImGuiInputTextState* GetInputTextState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.InputTextState.ID == id) ? &g.InputTextState : NULL; } // Get input text state if active IMGUI_API void SetNextItemRefVal(ImGuiDataType data_type, void* p_data); + inline bool IsItemActiveAsInputText() { ImGuiContext& g = *GImGui; return g.ActiveId != 0 && g.ActiveId == g.LastItemData.ID && g.InputTextState.ID == g.LastItemData.ID; } // This may be useful to apply workaround that a based on distinguish whenever an item is active as a text input field. // Color IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags); From 4c0604ec2ee9a9121ea4ecb55543ff507ca81bcc Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 18 Jan 2025 16:03:46 +0100 Subject: [PATCH 08/15] Font: shallow refactor, rename ConfigData[] fields to Sources[], ConfigDataCount to SourcesCount. In theory this is all internal stuff. --- imgui.cpp | 12 ++-- imgui.h | 10 +-- imgui_draw.cpp | 114 +++++++++++++++---------------- imgui_internal.h | 6 +- misc/freetype/imgui_freetype.cpp | 54 +++++++-------- 5 files changed, 98 insertions(+), 98 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a5d52d415..64514028f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -16215,7 +16215,7 @@ void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, co void ImGui::DebugNodeFont(ImFont* font) { bool opened = TreeNode(font, "Font: \"%s\": %.2f px, %d glyphs, %d sources(s)", - font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size, font->ConfigDataCount); + font->Sources ? font->Sources[0].Name : "", font->FontSize, font->Glyphs.Size, font->SourcesCount); // Display preview text if (!opened) @@ -16248,14 +16248,14 @@ void ImGui::DebugNodeFont(ImFont* font) Text("Ellipsis character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->EllipsisChar), font->EllipsisChar); const int surface_sqrt = (int)ImSqrt((float)font->MetricsTotalSurface); Text("Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, surface_sqrt, surface_sqrt); - for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) - if (font->ConfigData) + for (int config_i = 0; config_i < font->SourcesCount; config_i++) + if (font->Sources) { - const ImFontConfig* cfg = &font->ConfigData[config_i]; + const ImFontConfig* src = &font->Sources[config_i]; int oversample_h, oversample_v; - ImFontAtlasBuildGetOversampleFactors(cfg, &oversample_h, &oversample_v); + ImFontAtlasBuildGetOversampleFactors(src, &oversample_h, &oversample_v); BulletText("Input %d: \'%s\', Oversample: (%d=>%d,%d=>%d), PixelSnapH: %d, Offset: (%.1f,%.1f)", - config_i, cfg->Name, cfg->OversampleH, oversample_h, cfg->OversampleV, oversample_v, cfg->PixelSnapH, cfg->GlyphOffset.x, cfg->GlyphOffset.y); + config_i, src->Name, src->OversampleH, oversample_h, src->OversampleV, oversample_v, src->PixelSnapH, src->GlyphOffset.x, src->GlyphOffset.y); } // Display all glyphs of the fonts in separate pages of 256 characters diff --git a/imgui.h b/imgui.h index 5cba09f1c..1bdc2cb10 100644 --- a/imgui.h +++ b/imgui.h @@ -3441,7 +3441,7 @@ struct ImFontAtlas ImVec2 TexUvWhitePixel; // Texture coordinates to a white pixel ImVector Fonts; // Hold all the fonts returned by AddFont*. Fonts[0] is the default font upon calling ImGui::NewFrame(), use ImGui::PushFont()/PopFont() to change the current font. ImVector CustomRects; // Rectangles for packing custom texture data into the atlas. - ImVector ConfigData; // Configuration data + ImVector Sources; // Source/configuration data ImVec4 TexUvLines[IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1]; // UVs for baked anti-aliased lines // [Internal] Font builder @@ -3472,10 +3472,10 @@ struct ImFont ImFontGlyph* FallbackGlyph; // 4-8 // out // = FindGlyph(FontFallbackChar) // [Internal] Members: Cold ~32/40 bytes - // Conceptually ConfigData[] is the list of font sources merged to create this font. + // Conceptually Sources[] is the list of font sources merged to create this font. ImFontAtlas* ContainerAtlas; // 4-8 // out // What we has been loaded into - const ImFontConfig* ConfigData; // 4-8 // in // Pointer within ContainerAtlas->ConfigData to ConfigDataCount instances - short ConfigDataCount; // 2 // in // Number of ImFontConfig involved in creating this font. Usually 1, or >1 when merging multiple font sources into one ImFont. + ImFontConfig* Sources; // 4-8 // in // Pointer within ContainerAtlas->Sources[], to SourcesCount instances + short SourcesCount; // 2 // in // Number of ImFontConfig involved in creating this font. Usually 1, or >1 when merging multiple font sources into one ImFont. short EllipsisCharCount; // 1 // out // 1 or 3 ImWchar EllipsisChar; // 2-4 // out // Character used for ellipsis rendering ('...'). ImWchar FallbackChar; // 2-4 // out // Character used if a glyph isn't found (U+FFFD, '?') @@ -3494,7 +3494,7 @@ struct ImFont IMGUI_API ImFontGlyph* FindGlyphNoFallback(ImWchar c); float GetCharAdvance(ImWchar c) { return ((int)c < IndexAdvanceX.Size) ? IndexAdvanceX[(int)c] : FallbackAdvanceX; } bool IsLoaded() const { return ContainerAtlas != NULL; } - const char* GetDebugName() const { return ConfigData ? ConfigData->Name : ""; } + const char* GetDebugName() const { return Sources ? Sources->Name : ""; } // [Internal] Don't use! // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable. diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 3fd71cf3c..206c29ce5 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2408,7 +2408,7 @@ ImFontConfig::ImFontConfig() // - ImFontAtlasBuildMultiplyRectAlpha8() // - ImFontAtlasBuildWithStbTruetype() // - ImFontAtlasGetBuilderForStbTruetype() -// - ImFontAtlasUpdateConfigDataPointers() +// - ImFontAtlasUpdateSourcesPointers() // - ImFontAtlasBuildSetupFont() // - ImFontAtlasBuildPackCustomRects() // - ImFontAtlasBuildRender8bppRectFromString() @@ -2487,7 +2487,7 @@ ImFontAtlas::~ImFontAtlas() void ImFontAtlas::ClearInputData() { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); - for (ImFontConfig& font_cfg : ConfigData) + for (ImFontConfig& font_cfg : Sources) if (font_cfg.FontData && font_cfg.FontDataOwnedByAtlas) { IM_FREE(font_cfg.FontData); @@ -2496,12 +2496,12 @@ void ImFontAtlas::ClearInputData() // When clearing this we lose access to the font name and other information used to build the font. for (ImFont* font : Fonts) - if (font->ConfigData >= ConfigData.Data && font->ConfigData < ConfigData.Data + ConfigData.Size) + if (font->Sources >= Sources.Data && font->Sources < Sources.Data + Sources.Size) { - font->ConfigData = NULL; - font->ConfigDataCount = 0; + font->Sources = NULL; + font->SourcesCount = 0; } - ConfigData.clear(); + Sources.clear(); CustomRects.clear(); PackIdMouseCursors = PackIdLines = -1; // Important: we leave TexReady untouched @@ -2584,8 +2584,8 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) else IM_ASSERT(Fonts.Size > 0 && "Cannot use MergeMode for the first font"); // When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font. - ConfigData.push_back(*font_cfg); - ImFontConfig& new_font_cfg = ConfigData.back(); + Sources.push_back(*font_cfg); + ImFontConfig& new_font_cfg = Sources.back(); if (new_font_cfg.DstFont == NULL) new_font_cfg.DstFont = Fonts.back(); if (!new_font_cfg.FontDataOwnedByAtlas) @@ -2601,8 +2601,8 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) // - We may support it better later and remove this rounding. new_font_cfg.SizePixels = ImTrunc(new_font_cfg.SizePixels); - // Pointers to ConfigData and BuilderData are otherwise dangling - ImFontAtlasUpdateConfigDataPointers(this); + // Pointers to Sources data are otherwise dangling + ImFontAtlasUpdateSourcesPointers(this); // Invalidate texture TexReady = false; @@ -2780,7 +2780,7 @@ bool ImFontAtlas::Build() IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); // Default font is none are specified - if (ConfigData.Size == 0) + if (Sources.Size == 0) AddFontDefault(); // Select builder @@ -2822,11 +2822,11 @@ void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsig *data = table[*data]; } -void ImFontAtlasBuildGetOversampleFactors(const ImFontConfig* cfg, int* out_oversample_h, int* out_oversample_v) +void ImFontAtlasBuildGetOversampleFactors(const ImFontConfig* src, int* out_oversample_h, int* out_oversample_v) { // Automatically disable horizontal oversampling over size 36 - *out_oversample_h = (cfg->OversampleH != 0) ? cfg->OversampleH : (cfg->SizePixels * cfg->RasterizerDensity > 36.0f || cfg->PixelSnapH) ? 1 : 2; - *out_oversample_v = (cfg->OversampleV != 0) ? cfg->OversampleV : 1; + *out_oversample_h = (src->OversampleH != 0) ? src->OversampleH : (src->SizePixels * src->RasterizerDensity > 36.0f || src->PixelSnapH) ? 1 : 2; + *out_oversample_v = (src->OversampleV != 0) ? src->OversampleV : 1; } #ifdef IMGUI_ENABLE_STB_TRUETYPE @@ -2869,7 +2869,7 @@ static void UnpackBitVectorToFlatIndexList(const ImBitVector* in, ImVector* static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) { - IM_ASSERT(atlas->ConfigData.Size > 0); + IM_ASSERT(atlas->Sources.Size > 0); ImFontAtlasBuildInit(atlas); @@ -2883,32 +2883,32 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) // Temporary storage for building ImVector src_tmp_array; ImVector dst_tmp_array; - src_tmp_array.resize(atlas->ConfigData.Size); + src_tmp_array.resize(atlas->Sources.Size); dst_tmp_array.resize(atlas->Fonts.Size); memset(src_tmp_array.Data, 0, (size_t)src_tmp_array.size_in_bytes()); memset(dst_tmp_array.Data, 0, (size_t)dst_tmp_array.size_in_bytes()); // 1. Initialize font loading structure, check font data validity - for (int src_i = 0; src_i < atlas->ConfigData.Size; src_i++) + for (int src_i = 0; src_i < atlas->Sources.Size; src_i++) { ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; - ImFontConfig& cfg = atlas->ConfigData[src_i]; - IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas)); + ImFontConfig& src = atlas->Sources[src_i]; + IM_ASSERT(src.DstFont && (!src.DstFont->IsLoaded() || src.DstFont->ContainerAtlas == atlas)); - // Find index from cfg.DstFont (we allow the user to set cfg.DstFont. Also it makes casual debugging nicer than when storing indices) + // Find index from src.DstFont (we allow the user to set cfg.DstFont. Also it makes casual debugging nicer than when storing indices) src_tmp.DstIndex = -1; for (int output_i = 0; output_i < atlas->Fonts.Size && src_tmp.DstIndex == -1; output_i++) - if (cfg.DstFont == atlas->Fonts[output_i]) + if (src.DstFont == atlas->Fonts[output_i]) src_tmp.DstIndex = output_i; if (src_tmp.DstIndex == -1) { - IM_ASSERT(src_tmp.DstIndex != -1); // cfg.DstFont not pointing within atlas->Fonts[] array? + IM_ASSERT(src_tmp.DstIndex != -1); // src.DstFont not pointing within atlas->Fonts[] array? return false; } // Initialize helper structure for font loading and verify that the TTF/OTF data is correct - const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)cfg.FontData, cfg.FontNo); + const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)src.FontData, src.FontNo); IM_ASSERT(font_offset >= 0 && "FontData is incorrect, or FontNo cannot be found."); - if (!stbtt_InitFont(&src_tmp.FontInfo, (unsigned char*)cfg.FontData, font_offset)) + if (!stbtt_InitFont(&src_tmp.FontInfo, (unsigned char*)src.FontData, font_offset)) { IM_ASSERT(0 && "stbtt_InitFont(): failed to parse FontData. It is correct and complete? Check FontDataSize."); return false; @@ -2916,7 +2916,7 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) // Measure highest codepoints ImFontBuildDstData& dst_tmp = dst_tmp_array[src_tmp.DstIndex]; - src_tmp.SrcRanges = cfg.GlyphRanges ? cfg.GlyphRanges : atlas->GetGlyphRangesDefault(); + src_tmp.SrcRanges = src.GlyphRanges ? src.GlyphRanges : atlas->GetGlyphRangesDefault(); for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) { // Check for valid range. This may also help detect *some* dangling pointers, because a common @@ -2995,12 +2995,12 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) buf_packedchars_out_n += src_tmp.GlyphsCount; // Automatic selection of oversampling parameters - ImFontConfig& cfg = atlas->ConfigData[src_i]; + ImFontConfig& src = atlas->Sources[src_i]; int oversample_h, oversample_v; - ImFontAtlasBuildGetOversampleFactors(&cfg, &oversample_h, &oversample_v); + ImFontAtlasBuildGetOversampleFactors(&src, &oversample_h, &oversample_v); // Convert our ranges in the format stb_truetype wants - src_tmp.PackRange.font_size = cfg.SizePixels * cfg.RasterizerDensity; + src_tmp.PackRange.font_size = src.SizePixels * src.RasterizerDensity; src_tmp.PackRange.first_unicode_codepoint_in_range = 0; src_tmp.PackRange.array_of_unicode_codepoints = src_tmp.GlyphsList.Data; src_tmp.PackRange.num_chars = src_tmp.GlyphsList.Size; @@ -3009,7 +3009,7 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) src_tmp.PackRange.v_oversample = (unsigned char)oversample_v; // Gather the sizes of all rectangles we will need to pack (this loop is based on stbtt_PackFontRangesGatherRects) - const float scale = (cfg.SizePixels > 0.0f) ? stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, cfg.SizePixels * cfg.RasterizerDensity) : stbtt_ScaleForMappingEmToPixels(&src_tmp.FontInfo, -cfg.SizePixels * cfg.RasterizerDensity); + const float scale = (src.SizePixels > 0.0f) ? stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, src.SizePixels * src.RasterizerDensity) : stbtt_ScaleForMappingEmToPixels(&src_tmp.FontInfo, -src.SizePixels * src.RasterizerDensity); for (int glyph_i = 0; glyph_i < src_tmp.GlyphsList.Size; glyph_i++) { int x0, y0, x1, y1; @@ -3069,7 +3069,7 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) // 8. Render/rasterize font characters into the texture for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) { - ImFontConfig& cfg = atlas->ConfigData[src_i]; + ImFontConfig& src = atlas->Sources[src_i]; ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; if (src_tmp.GlyphsCount == 0) continue; @@ -3077,10 +3077,10 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) stbtt_PackFontRangesRenderIntoRects(&spc, &src_tmp.FontInfo, &src_tmp.PackRange, 1, src_tmp.Rects); // Apply multiply operator - if (cfg.RasterizerMultiply != 1.0f) + if (src.RasterizerMultiply != 1.0f) { unsigned char multiply_table[256]; - ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply); + ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, src.RasterizerMultiply); stbrp_rect* r = &src_tmp.Rects[0]; for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++, r++) if (r->was_packed) @@ -3098,22 +3098,22 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) { // When merging fonts with MergeMode=true: // - We can have multiple input fonts writing into a same destination font. - // - dst_font->ConfigData is != from cfg which is our source configuration. + // - dst_font->Sources is != from src which is our source configuration. ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; - ImFontConfig& cfg = atlas->ConfigData[src_i]; - ImFont* dst_font = cfg.DstFont; + ImFontConfig& src = atlas->Sources[src_i]; + ImFont* dst_font = src.DstFont; - const float font_scale = stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, cfg.SizePixels); + const float font_scale = stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, src.SizePixels); int unscaled_ascent, unscaled_descent, unscaled_line_gap; stbtt_GetFontVMetrics(&src_tmp.FontInfo, &unscaled_ascent, &unscaled_descent, &unscaled_line_gap); const float ascent = ImCeil(unscaled_ascent * font_scale); const float descent = ImFloor(unscaled_descent * font_scale); - ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); - const float font_off_x = cfg.GlyphOffset.x; - const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent); + ImFontAtlasBuildSetupFont(atlas, dst_font, &src, ascent, descent); + const float font_off_x = src.GlyphOffset.x; + const float font_off_y = src.GlyphOffset.y + IM_ROUND(dst_font->Ascent); - const float inv_rasterization_scale = 1.0f / cfg.RasterizerDensity; + const float inv_rasterization_scale = 1.0f / src.RasterizerDensity; for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) { @@ -3127,7 +3127,7 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) float y0 = q.y0 * inv_rasterization_scale + font_off_y; float x1 = q.x1 * inv_rasterization_scale + font_off_x; float y1 = q.y1 * inv_rasterization_scale + font_off_y; - dst_font->AddGlyph(&cfg, (ImWchar)codepoint, x0, y0, x1, y1, q.s0, q.t0, q.s1, q.t1, pc.xadvance * inv_rasterization_scale); + dst_font->AddGlyph(&src, (ImWchar)codepoint, x0, y0, x1, y1, q.s0, q.t0, q.s1, q.t1, pc.xadvance * inv_rasterization_scale); } } @@ -3147,17 +3147,17 @@ const ImFontBuilderIO* ImFontAtlasGetBuilderForStbTruetype() #endif // IMGUI_ENABLE_STB_TRUETYPE -void ImFontAtlasUpdateConfigDataPointers(ImFontAtlas* atlas) +void ImFontAtlasUpdateSourcesPointers(ImFontAtlas* atlas) { - for (ImFontConfig& font_cfg : atlas->ConfigData) + for (ImFontConfig& src : atlas->Sources) { - ImFont* font = font_cfg.DstFont; - if (!font_cfg.MergeMode) + ImFont* font = src.DstFont; + if (!src.MergeMode) { - font->ConfigData = &font_cfg; - font->ConfigDataCount = 0; + font->Sources = &src; + font->SourcesCount = 0; } - font->ConfigDataCount++; + font->SourcesCount++; } } @@ -3167,7 +3167,7 @@ void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* f { font->ClearOutputData(); font->FontSize = font_config->SizePixels; - IM_ASSERT(font->ConfigData == font_config); + IM_ASSERT(font->Sources == font_config); font->ContainerAtlas = atlas; font->Ascent = ascent; font->Descent = descent; @@ -3786,7 +3786,7 @@ void ImFont::BuildLookupTable() // Setup Ellipsis character. It is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis). // However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character. // FIXME: Note that 0x2026 is rarely included in our font ranges. Because of this we are more likely to use three individual dots. - const ImWchar ellipsis_chars[] = { ConfigData->EllipsisChar, (ImWchar)0x2026, (ImWchar)0x0085 }; + const ImWchar ellipsis_chars[] = { Sources->EllipsisChar, (ImWchar)0x2026, (ImWchar)0x0085 }; const ImWchar dots_chars[] = { (ImWchar)'.', (ImWchar)0xFF0E }; if (EllipsisChar == 0) EllipsisChar = FindFirstExistingGlyph(this, ellipsis_chars, IM_ARRAYSIZE(ellipsis_chars)); @@ -3830,27 +3830,27 @@ void ImFont::GrowIndex(int new_size) // x0/y0/x1/y1 are offset from the character upper-left layout position, in pixels. Therefore x0/y0 are often fairly close to zero. // Not to be mistaken with texture coordinates, which are held by u0/v0/u1/v1 in normalized format (0.0..1.0 on each texture axis). -// 'cfg' is not necessarily == 'this->ConfigData' because multiple source fonts+configs can be used to build one target font. -void ImFont::AddGlyph(const ImFontConfig* cfg, ImWchar codepoint, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x) +// 'src' is not necessarily == 'this->Sources' because multiple source fonts+configs can be used to build one target font. +void ImFont::AddGlyph(const ImFontConfig* src, ImWchar codepoint, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x) { - if (cfg != NULL) + if (src != NULL) { // Clamp & recenter if needed const float advance_x_original = advance_x; - advance_x = ImClamp(advance_x, cfg->GlyphMinAdvanceX, cfg->GlyphMaxAdvanceX); + advance_x = ImClamp(advance_x, src->GlyphMinAdvanceX, src->GlyphMaxAdvanceX); if (advance_x != advance_x_original) { - float char_off_x = cfg->PixelSnapH ? ImTrunc((advance_x - advance_x_original) * 0.5f) : (advance_x - advance_x_original) * 0.5f; + float char_off_x = src->PixelSnapH ? ImTrunc((advance_x - advance_x_original) * 0.5f) : (advance_x - advance_x_original) * 0.5f; x0 += char_off_x; x1 += char_off_x; } // Snap to pixel - if (cfg->PixelSnapH) + if (src->PixelSnapH) advance_x = IM_ROUND(advance_x); // Bake extra spacing - advance_x += cfg->GlyphExtraAdvanceX; + advance_x += src->GlyphExtraAdvanceX; } int glyph_idx = Glyphs.Size; diff --git a/imgui_internal.h b/imgui_internal.h index c4ec9cc93..c70bb999c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3577,16 +3577,16 @@ struct ImFontBuilderIO #ifdef IMGUI_ENABLE_STB_TRUETYPE IMGUI_API const ImFontBuilderIO* ImFontAtlasGetBuilderForStbTruetype(); #endif -IMGUI_API void ImFontAtlasUpdateConfigDataPointers(ImFontAtlas* atlas); +IMGUI_API void ImFontAtlasUpdateSourcesPointers(ImFontAtlas* atlas); IMGUI_API void ImFontAtlasBuildInit(ImFontAtlas* atlas); -IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent); +IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* src, float ascent, float descent); IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opaque); IMGUI_API void ImFontAtlasBuildFinish(ImFontAtlas* atlas); IMGUI_API void ImFontAtlasBuildRender8bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned char in_marker_pixel_value); IMGUI_API void ImFontAtlasBuildRender32bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned int in_marker_pixel_value); IMGUI_API void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_multiply_factor); IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride); -IMGUI_API void ImFontAtlasBuildGetOversampleFactors(const ImFontConfig* cfg, int* out_oversample_h, int* out_oversample_v); +IMGUI_API void ImFontAtlasBuildGetOversampleFactors(const ImFontConfig* src, int* out_oversample_h, int* out_oversample_v); IMGUI_API bool ImFontAtlasGetMouseCursorTexData(ImFontAtlas* atlas, ImGuiMouseCursor cursor_type, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]); diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 875060d7f..73b9862bc 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -166,7 +166,7 @@ namespace // NB: No ctor/dtor, explicitly call Init()/Shutdown() struct FreeTypeFont { - bool InitFont(FT_Library ft_library, const ImFontConfig& cfg, unsigned int extra_user_flags); // Initialize from an external data buffer. Doesn't copy data, and you must ensure it stays valid up to this object lifetime. + bool InitFont(FT_Library ft_library, const ImFontConfig& src, unsigned int extra_user_flags); // Initialize from an external data buffer. Doesn't copy data, and you must ensure it stays valid up to this object lifetime. void CloseFont(); void SetPixelHeight(int pixel_height); // Change font pixel size. All following calls to RasterizeGlyph() will use this size const FT_Glyph_Metrics* LoadGlyph(uint32_t in_codepoint); @@ -185,9 +185,9 @@ namespace float InvRasterizationDensity; }; - bool FreeTypeFont::InitFont(FT_Library ft_library, const ImFontConfig& cfg, unsigned int extra_font_builder_flags) + bool FreeTypeFont::InitFont(FT_Library ft_library, const ImFontConfig& src, unsigned int extra_font_builder_flags) { - FT_Error error = FT_New_Memory_Face(ft_library, (uint8_t*)cfg.FontData, (uint32_t)cfg.FontDataSize, (uint32_t)cfg.FontNo, &Face); + FT_Error error = FT_New_Memory_Face(ft_library, (uint8_t*)src.FontData, (uint32_t)src.FontDataSize, (uint32_t)src.FontNo, &Face); if (error != 0) return false; error = FT_Select_Charmap(Face, FT_ENCODING_UNICODE); @@ -195,7 +195,7 @@ namespace return false; // Convert to FreeType flags (NB: Bold and Oblique are processed separately) - UserFlags = cfg.FontBuilderFlags | extra_font_builder_flags; + UserFlags = src.FontBuilderFlags | extra_font_builder_flags; LoadFlags = 0; if ((UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) == 0) @@ -222,11 +222,11 @@ namespace if (UserFlags & ImGuiFreeTypeBuilderFlags_LoadColor) LoadFlags |= FT_LOAD_COLOR; - RasterizationDensity = cfg.RasterizerDensity; + RasterizationDensity = src.RasterizerDensity; InvRasterizationDensity = 1.0f / RasterizationDensity; memset(&Info, 0, sizeof(Info)); - SetPixelHeight((uint32_t)cfg.SizePixels); + SetPixelHeight((uint32_t)src.SizePixels); return true; } @@ -443,7 +443,7 @@ struct ImFontBuildDstDataFT bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, unsigned int extra_flags) { - IM_ASSERT(atlas->ConfigData.Size > 0); + IM_ASSERT(atlas->Sources.Size > 0); ImFontAtlasBuildInit(atlas); @@ -458,36 +458,36 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u bool src_load_color = false; ImVector src_tmp_array; ImVector dst_tmp_array; - src_tmp_array.resize(atlas->ConfigData.Size); + src_tmp_array.resize(atlas->Sources.Size); dst_tmp_array.resize(atlas->Fonts.Size); memset((void*)src_tmp_array.Data, 0, (size_t)src_tmp_array.size_in_bytes()); memset((void*)dst_tmp_array.Data, 0, (size_t)dst_tmp_array.size_in_bytes()); // 1. Initialize font loading structure, check font data validity - for (int src_i = 0; src_i < atlas->ConfigData.Size; src_i++) + for (int src_i = 0; src_i < atlas->Sources.Size; src_i++) { ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; - ImFontConfig& cfg = atlas->ConfigData[src_i]; + ImFontConfig& src = atlas->Sources[src_i]; FreeTypeFont& font_face = src_tmp.Font; - IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas)); + IM_ASSERT(src.DstFont && (!src.DstFont->IsLoaded() || src.DstFont->ContainerAtlas == atlas)); - // Find index from cfg.DstFont (we allow the user to set cfg.DstFont. Also it makes casual debugging nicer than when storing indices) + // Find index from src.DstFont (we allow the user to set cfg.DstFont. Also it makes casual debugging nicer than when storing indices) src_tmp.DstIndex = -1; for (int output_i = 0; output_i < atlas->Fonts.Size && src_tmp.DstIndex == -1; output_i++) - if (cfg.DstFont == atlas->Fonts[output_i]) + if (src.DstFont == atlas->Fonts[output_i]) src_tmp.DstIndex = output_i; - IM_ASSERT(src_tmp.DstIndex != -1); // cfg.DstFont not pointing within atlas->Fonts[] array? + IM_ASSERT(src_tmp.DstIndex != -1); // src.DstFont not pointing within atlas->Fonts[] array? if (src_tmp.DstIndex == -1) return false; // Load font - if (!font_face.InitFont(ft_library, cfg, extra_flags)) + if (!font_face.InitFont(ft_library, src, extra_flags)) return false; // Measure highest codepoints - src_load_color |= (cfg.FontBuilderFlags & ImGuiFreeTypeBuilderFlags_LoadColor) != 0; + src_load_color |= (src.FontBuilderFlags & ImGuiFreeTypeBuilderFlags_LoadColor) != 0; ImFontBuildDstDataFT& dst_tmp = dst_tmp_array[src_tmp.DstIndex]; - src_tmp.SrcRanges = cfg.GlyphRanges ? cfg.GlyphRanges : atlas->GetGlyphRangesDefault(); + src_tmp.SrcRanges = src.GlyphRanges ? src.GlyphRanges : atlas->GetGlyphRangesDefault(); for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) { // Check for valid range. This may also help detect *some* dangling pointers, because a common @@ -577,7 +577,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) { ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; - ImFontConfig& cfg = atlas->ConfigData[src_i]; + ImFontConfig& src = atlas->Sources[src_i]; if (src_tmp.GlyphsCount == 0) continue; @@ -585,10 +585,10 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u buf_rects_out_n += src_tmp.GlyphsCount; // Compute multiply table if requested - const bool multiply_enabled = (cfg.RasterizerMultiply != 1.0f); + const bool multiply_enabled = (src.RasterizerMultiply != 1.0f); unsigned char multiply_table[256]; if (multiply_enabled) - ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply); + ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, src.RasterizerMultiply); // Gather the sizes of all rectangles we will need to pack for (int glyph_i = 0; glyph_i < src_tmp.GlyphsList.Size; glyph_i++) @@ -687,18 +687,18 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u // When merging fonts with MergeMode=true: // - We can have multiple input fonts writing into a same destination font. - // - dst_font->ConfigData is != from cfg which is our source configuration. - ImFontConfig& cfg = atlas->ConfigData[src_i]; - ImFont* dst_font = cfg.DstFont; + // - dst_font->Sources is != from src which is our source configuration. + ImFontConfig& src = atlas->Sources[src_i]; + ImFont* dst_font = src.DstFont; const float ascent = src_tmp.Font.Info.Ascender; const float descent = src_tmp.Font.Info.Descender; - ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); + ImFontAtlasBuildSetupFont(atlas, dst_font, &src, ascent, descent); if (src_tmp.GlyphsCount == 0) continue; - const float font_off_x = cfg.GlyphOffset.x; - const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent); + const float font_off_x = src.GlyphOffset.x; + const float font_off_y = src.GlyphOffset.y + IM_ROUND(dst_font->Ascent); const int padding = atlas->TexGlyphPadding; for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) @@ -724,7 +724,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u float v0 = (ty) / (float)atlas->TexHeight; float u1 = (tx + info.Width) / (float)atlas->TexWidth; float v1 = (ty + info.Height) / (float)atlas->TexHeight; - dst_font->AddGlyph(&cfg, (ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX * src_tmp.Font.InvRasterizationDensity); + dst_font->AddGlyph(&src, (ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX * src_tmp.Font.InvRasterizationDensity); ImFontGlyph* dst_glyph = &dst_font->Glyphs.back(); IM_ASSERT(dst_glyph->Codepoint == src_glyph.Codepoint); From a86fcbd9474bb4121f25cbf9196674d79f90f1f1 Mon Sep 17 00:00:00 2001 From: Russ Gibson Date: Wed, 26 Feb 2025 05:38:08 -0800 Subject: [PATCH 09/15] Examples: SDL3+SDL_Renderer: removed reference to OpenGL to remove confusion. (#8434) --- examples/example_sdl3_sdlrenderer3/Makefile | 2 +- examples/example_sdl3_sdlrenderer3/main.cpp | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/examples/example_sdl3_sdlrenderer3/Makefile b/examples/example_sdl3_sdlrenderer3/Makefile index 2ca986545..c7ee64fc7 100644 --- a/examples/example_sdl3_sdlrenderer3/Makefile +++ b/examples/example_sdl3_sdlrenderer3/Makefile @@ -44,7 +44,7 @@ endif ifeq ($(OS), Windows_NT) ECHO_MESSAGE = "MinGW" - LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl3` + LIBS += -lgdi32 -limm32 `pkg-config --static --libs sdl3` CXXFLAGS += `pkg-config --cflags sdl3` CFLAGS = $(CXXFLAGS) diff --git a/examples/example_sdl3_sdlrenderer3/main.cpp b/examples/example_sdl3_sdlrenderer3/main.cpp index 483350fcb..68078eebd 100644 --- a/examples/example_sdl3_sdlrenderer3/main.cpp +++ b/examples/example_sdl3_sdlrenderer3/main.cpp @@ -15,11 +15,6 @@ #include "imgui_impl_sdlrenderer3.h" #include #include -#if defined(IMGUI_IMPL_OPENGL_ES2) -#include -#else -#include -#endif #ifdef __EMSCRIPTEN__ #include "../libs/emscripten/emscripten_mainloop_stub.h" @@ -36,7 +31,7 @@ int main(int, char**) } // Create window with SDL_Renderer graphics context - Uint32 window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN; + Uint32 window_flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN; SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+SDL_Renderer example", 1280, 720, window_flags); if (window == nullptr) { From 242d856ede78544a6ed2debea3afecad884630c6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 26 Feb 2025 14:40:41 +0100 Subject: [PATCH 10/15] Examples: SDL3+SDL_Renderer: removed reference to OpenGL to remove confusion. (#8434) Amend --- examples/example_sdl3_sdlrenderer3/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_sdl3_sdlrenderer3/Makefile b/examples/example_sdl3_sdlrenderer3/Makefile index c7ee64fc7..1976fa924 100644 --- a/examples/example_sdl3_sdlrenderer3/Makefile +++ b/examples/example_sdl3_sdlrenderer3/Makefile @@ -34,7 +34,7 @@ endif ifeq ($(UNAME_S), Darwin) #APPLE ECHO_MESSAGE = "Mac OS X" - LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl3-config --libs` + LIBS += -framework Cocoa -framework IOKit -framework CoreVideo `sdl3-config --libs` LIBS += -L/usr/local/lib -L/opt/local/lib CXXFLAGS += `pkg-config sdl3 --cflags` From 4f4fb1d220d31ca8b04163ed80bed7108e6429bc Mon Sep 17 00:00:00 2001 From: "Jose L. Hidalgo (PpluX)" Date: Sat, 22 Feb 2025 12:47:30 +0100 Subject: [PATCH 11/15] Backends: WebGPU: update code for latest webgpu-native changes. (#8426) --- backends/imgui_impl_wgpu.cpp | 22 ++++++++++++---------- docs/CHANGELOG.txt | 3 ++- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index a81662d84..36d053e2b 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -17,6 +17,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-26: Update for latest webgpu-native changes. // 2024-10-14: Update Dawn support for change of string usages. (#8082, #8083) // 2024-10-07: Expose selected render state in ImGui_ImplWGPU_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. // 2024-10-07: Changed default texture sampler to Clamp instead of Repeat/Wrap. @@ -65,7 +66,7 @@ using WGPUProgrammableStageDescriptor = WGPUComputeState; #endif // Dear ImGui prototypes from imgui_internal.h -extern ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed = 0); +extern ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed); #define MEMALIGN(_SIZE,_ALIGN) (((_SIZE) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1)) // Memory align (copied from IM_ALIGN() macro). // WebGPU data @@ -267,7 +268,7 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c { ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData(); -#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) WGPUShaderSourceWGSL wgsl_desc = {}; wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL; wgsl_desc.code = { wgsl_source, WGPU_STRLEN }; @@ -282,7 +283,8 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c WGPUProgrammableStageDescriptor stage_desc = {}; stage_desc.module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc); -#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN + +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) stage_desc.entryPoint = { "main", WGPU_STRLEN }; #else stage_desc.entryPoint = "main"; @@ -399,7 +401,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder { nullptr, "Dear ImGui Vertex buffer", -#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) WGPU_STRLEN, #endif WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex, @@ -426,7 +428,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder { nullptr, "Dear ImGui Index buffer", -#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) WGPU_STRLEN, #endif WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index, @@ -539,7 +541,7 @@ static void ImGui_ImplWGPU_CreateFontsTexture() // Upload texture to graphics system { WGPUTextureDescriptor tex_desc = {}; -#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) tex_desc.label = { "Dear ImGui Font Texture", WGPU_STRLEN }; #else tex_desc.label = "Dear ImGui Font Texture"; @@ -567,12 +569,12 @@ static void ImGui_ImplWGPU_CreateFontsTexture() // Upload texture data { - WGPUImageCopyTexture dst_view = {}; + WGPUTexelCopyTextureInfo dst_view = {}; dst_view.texture = bd->renderResources.FontTexture; dst_view.mipLevel = 0; dst_view.origin = { 0, 0, 0 }; dst_view.aspect = WGPUTextureAspect_All; - WGPUTextureDataLayout layout = {}; + WGPUTexelCopyBufferLayout layout = {}; layout.offset = 0; layout.bytesPerRow = width * size_pp; layout.rowsPerImage = height; @@ -606,7 +608,7 @@ static void ImGui_ImplWGPU_CreateUniformBuffer() { nullptr, "Dear ImGui Uniform buffer", -#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) WGPU_STRLEN, #endif WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform, @@ -714,7 +716,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() // Create depth-stencil State WGPUDepthStencilState depth_stencil_state = {}; depth_stencil_state.format = bd->depthStencilFormat; -#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) depth_stencil_state.depthWriteEnabled = WGPUOptionalBool_False; #else depth_stencil_state.depthWriteEnabled = false; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d5c4ded32..b3af5d94c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -104,8 +104,9 @@ Other changes: Default to header version if unspecified. (#8326, #8365) [@mklefrancois] - Backends: Vulkan: Dynamic rendering path loads "vkCmdBeginRendering/vkCmdEndRendering" (without -KHR suffix) on API 1.3. (#8326, #8365) [@mklefrancois] -- Backends: WebGPU: Fix for DAWN API rename WGPUProgrammableStageDescriptor -> WGPUComputeState. +- Backends: WebGPU: Fix for DAWN API change WGPUProgrammableStageDescriptor -> WGPUComputeState. [@PhantomCloak] (#8369) +- Backends: WebGPU: Fix for webgpu-native API changes. (#8426) [@pplux] ----------------------------------------------------------------------- From 6aa0810de5dad4add4e73ff6352df63429f921ee Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 26 Feb 2025 15:10:28 +0100 Subject: [PATCH 12/15] Backends: WebGPU: update code for latest webgpu-native changes. Amend. (#8426) --- backends/imgui_impl_wgpu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 36d053e2b..45eaeba64 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -493,7 +493,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder { // Bind custom texture ImTextureID tex_id = pcmd->GetTexID(); - ImGuiID tex_id_hash = ImHashData(&tex_id, sizeof(tex_id)); + ImGuiID tex_id_hash = ImHashData(&tex_id, sizeof(tex_id), 0); auto bind_group = bd->renderResources.ImageBindGroups.GetVoidPtr(tex_id_hash); if (bind_group) { @@ -755,7 +755,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup(bg_layouts[1], bd->renderResources.FontTextureView); bd->renderResources.ImageBindGroup = image_bind_group; bd->renderResources.ImageBindGroupLayout = bg_layouts[1]; - bd->renderResources.ImageBindGroups.SetVoidPtr(ImHashData(&bd->renderResources.FontTextureView, sizeof(ImTextureID)), image_bind_group); + bd->renderResources.ImageBindGroups.SetVoidPtr(ImHashData(&bd->renderResources.FontTextureView, sizeof(ImTextureID), 0), image_bind_group); SafeRelease(vertex_shader_desc.module); SafeRelease(pixel_shader_desc.module); From 9996a2d51b47e8679936f58de31f6df382a83689 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 26 Feb 2025 15:16:38 +0100 Subject: [PATCH 13/15] Backends: WebGPU: update code for latest webgpu-native changes. Fix for Emscripten. (#8426) --- backends/imgui_impl_wgpu.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 45eaeba64..4fffa23a5 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -569,12 +569,20 @@ static void ImGui_ImplWGPU_CreateFontsTexture() // Upload texture data { +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) WGPUTexelCopyTextureInfo dst_view = {}; +#else + WGPUImageCopyTexture dst_view = {}; +#endif dst_view.texture = bd->renderResources.FontTexture; dst_view.mipLevel = 0; dst_view.origin = { 0, 0, 0 }; dst_view.aspect = WGPUTextureAspect_All; +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) WGPUTexelCopyBufferLayout layout = {}; +#else + WGPUTextureDataLayout layout = {}; +#endif layout.offset = 0; layout.bytesPerRow = width * size_pp; layout.rowsPerImage = height; From aaacb01b8d4441453928116240b5041625d43fbf Mon Sep 17 00:00:00 2001 From: "Jose L. Hidalgo (PpluX)" Date: Wed, 26 Feb 2025 15:19:56 +0100 Subject: [PATCH 14/15] Backends: WebGPU: Recreate image bind groups during render. (#8426, #8046, #7765, #8027) --- backends/imgui_impl_wgpu.cpp | 33 ++++++++++++++++----------------- docs/CHANGELOG.txt | 2 ++ 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 4fffa23a5..b04ac3bb7 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -17,7 +17,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2025-02-26: Update for latest webgpu-native changes. +// 2025-02-26: Recreate image bind groups during render. (#8426, #8046, #7765, #8027) + Update for latest webgpu-native changes. // 2024-10-14: Update Dawn support for change of string usages. (#8082, #8083) // 2024-10-07: Expose selected render state in ImGui_ImplWGPU_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. // 2024-10-07: Changed default texture sampler to Clamp instead of Repeat/Wrap. @@ -78,7 +78,6 @@ struct RenderResources WGPUBuffer Uniforms = nullptr; // Shader uniforms WGPUBindGroup CommonBindGroup = nullptr; // Resources bind-group to bind the common resources to pipeline ImGuiStorage ImageBindGroups; // Resources bind-group to bind the font/image resources to pipeline (this is a key->value map) - WGPUBindGroup ImageBindGroup = nullptr; // Default font-resource of Dear ImGui WGPUBindGroupLayout ImageBindGroupLayout = nullptr; // Cache layout used for the image bind group. Avoids allocating unnecessary JS objects when working with WebASM }; @@ -252,7 +251,6 @@ static void SafeRelease(RenderResources& res) SafeRelease(res.Sampler); SafeRelease(res.Uniforms); SafeRelease(res.CommonBindGroup); - SafeRelease(res.ImageBindGroup); SafeRelease(res.ImageBindGroupLayout); }; @@ -494,17 +492,13 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder // Bind custom texture ImTextureID tex_id = pcmd->GetTexID(); ImGuiID tex_id_hash = ImHashData(&tex_id, sizeof(tex_id), 0); - auto bind_group = bd->renderResources.ImageBindGroups.GetVoidPtr(tex_id_hash); - if (bind_group) + WGPUBindGroup bind_group = (WGPUBindGroup)bd->renderResources.ImageBindGroups.GetVoidPtr(tex_id_hash); + if (!bind_group) { - wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, (WGPUBindGroup)bind_group, 0, nullptr); - } - else - { - WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup(bd->renderResources.ImageBindGroupLayout, (WGPUTextureView)tex_id); - bd->renderResources.ImageBindGroups.SetVoidPtr(tex_id_hash, image_bind_group); - wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, image_bind_group, 0, nullptr); + bind_group = ImGui_ImplWGPU_CreateImageBindGroup(bd->renderResources.ImageBindGroupLayout, (WGPUTextureView)tex_id); + bd->renderResources.ImageBindGroups.SetVoidPtr(tex_id_hash, bind_group); } + wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, (WGPUBindGroup)bind_group, 0, nullptr); // 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); @@ -526,6 +520,16 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder global_idx_offset += draw_list->IdxBuffer.Size; global_vtx_offset += draw_list->VtxBuffer.Size; } + + // Remove all ImageBindGroups + ImGuiStorage& image_bind_groups = bd->renderResources.ImageBindGroups; + for (int i = 0; i < image_bind_groups.Data.Size; i++) + { + WGPUBindGroup bind_group = (WGPUBindGroup)image_bind_groups.Data[i].val_p; + SafeRelease(bind_group); + } + image_bind_groups.Data.resize(0); + platform_io.Renderer_RenderState = nullptr; } @@ -759,11 +763,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() common_bg_descriptor.entryCount = sizeof(common_bg_entries) / sizeof(WGPUBindGroupEntry); common_bg_descriptor.entries = common_bg_entries; bd->renderResources.CommonBindGroup = wgpuDeviceCreateBindGroup(bd->wgpuDevice, &common_bg_descriptor); - - WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup(bg_layouts[1], bd->renderResources.FontTextureView); - bd->renderResources.ImageBindGroup = image_bind_group; bd->renderResources.ImageBindGroupLayout = bg_layouts[1]; - bd->renderResources.ImageBindGroups.SetVoidPtr(ImHashData(&bd->renderResources.FontTextureView, sizeof(ImTextureID), 0), image_bind_group); SafeRelease(vertex_shader_desc.module); SafeRelease(pixel_shader_desc.module); @@ -823,7 +823,6 @@ bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info) bd->renderResources.Uniforms = nullptr; bd->renderResources.CommonBindGroup = nullptr; bd->renderResources.ImageBindGroups.Data.reserve(100); - bd->renderResources.ImageBindGroup = nullptr; bd->renderResources.ImageBindGroupLayout = nullptr; // Create buffers with a default size (they will later be grown as needed) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b3af5d94c..ff249c140 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -104,6 +104,8 @@ Other changes: Default to header version if unspecified. (#8326, #8365) [@mklefrancois] - Backends: Vulkan: Dynamic rendering path loads "vkCmdBeginRendering/vkCmdEndRendering" (without -KHR suffix) on API 1.3. (#8326, #8365) [@mklefrancois] +- Backends: WebGPU: Recreate image bind groups during render to allow reuse of + WGPUTextureView pointers. (#8426, #8046, #7765, #8027) [@pplux, @Jairard] - Backends: WebGPU: Fix for DAWN API change WGPUProgrammableStageDescriptor -> WGPUComputeState. [@PhantomCloak] (#8369) - Backends: WebGPU: Fix for webgpu-native API changes. (#8426) [@pplux] From aa83d5d455dcab4b65cca71efd6291f943feea67 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 26 Feb 2025 15:34:31 +0100 Subject: [PATCH 15/15] Backends: SDL2, SDL3: Only start SDL_CaptureMouse() when mouse is being dragged. (#6410, #3650) To mitigate issues with e.g. Linux debuggers not claiming capture back. --- backends/imgui_impl_sdl2.cpp | 11 +++++++++-- backends/imgui_impl_sdl3.cpp | 11 +++++++++-- docs/CHANGELOG.txt | 2 ++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 361fc3b57..6256b4ddd 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-26: Only start SDL_CaptureMouse() when mouse is being dragged, to mitigate issues with e.g.Linux debuggers not claiming capture back. (#6410, #3650) // 2025-02-24: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode. // 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. // 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. @@ -609,8 +610,14 @@ static void ImGui_ImplSDL2_UpdateMouseData() // We forward mouse input when hovered or captured (via SDL_MOUSEMOTION) or when focused (below) #if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE - // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside - SDL_CaptureMouse((bd->MouseButtonsDown != 0) ? SDL_TRUE : SDL_FALSE); + // - SDL_CaptureMouse() let the OS know e.g. that our drags can extend outside of parent boundaries (we want updated position) and shouldn't trigger other operations outside. + // - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to migitate the issue we wait until mouse has moved to begin capture. + bool want_capture = false; + for (int button_n = 0; button_n < ImGuiMouseButton_COUNT && !want_capture; button_n++) + if (ImGui::IsMouseDragging(button_n, 1.0f)) + want_capture = true; + SDL_CaptureMouse(want_capture ? SDL_TRUE : SDL_FALSE); + SDL_Window* focused_window = SDL_GetKeyboardFocus(); const bool is_app_focused = (bd->Window == focused_window); #else diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index d2433793e..2d8027184 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-26: Only start SDL_CaptureMouse() when mouse is being dragged, to mitigate issues with e.g.Linux debuggers not claiming capture back. (#6410, #3650) // 2025-02-24: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode. // 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. // 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. @@ -574,8 +575,14 @@ static void ImGui_ImplSDL3_UpdateMouseData() // We forward mouse input when hovered or captured (via SDL_EVENT_MOUSE_MOTION) or when focused (below) #if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE - // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside - SDL_CaptureMouse(bd->MouseButtonsDown != 0); + // - SDL_CaptureMouse() let the OS know e.g. that our drags can extend outside of parent boundaries (we want updated position) and shouldn't trigger other operations outside. + // - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to migitate the issue we wait until mouse has moved to begin capture. + bool want_capture = false; + for (int button_n = 0; button_n < ImGuiMouseButton_COUNT && !want_capture; button_n++) + if (ImGui::IsMouseDragging(button_n, 1.0f)) + want_capture = true; + SDL_CaptureMouse(want_capture); + SDL_Window* focused_window = SDL_GetKeyboardFocus(); const bool is_app_focused = (bd->Window == focused_window); #else diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ff249c140..5a1b63ad2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -95,6 +95,8 @@ Other changes: and ImGuiMouseCursor_Progress cursors. - Backends: SDL2, SDL3: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode. (#8425, #8407) [@TheMode] +- Backends: SDL2, SDL3: Only start SDL_CaptureMouse() when mouse is being dragged, + to mitigate issues with e.g. Linux debuggers not claiming capture back. (#6410, #3650) - Backends: OpenGL3: Lazily reinitialize embedded GL loader for when calling backend from e.g. other DLL boundaries. (#8406) - Backends: DirectX12: Fixed an issue where pre-1.91.5 legacy ImGui_ImplDX12_Init()