Compare commits

..

29 commits

Author SHA1 Message Date
Zane van Iperen
74e453cf15 Backends: SDL2, SDL3: don't attempt to call SDL_CaptureMouse() on drivers where we don't call SDL_GetGlobalMouseState(). (#8561)
Some checks are pending
build / Windows (push) Waiting to run
build / Linux (push) Waiting to run
build / MacOS (push) Waiting to run
build / iOS (push) Waiting to run
build / Emscripten (push) Waiting to run
build / Android (push) Waiting to run
2025-04-09 14:58:32 +02:00
ocornut
789de09dda TreeNode: extracted TreeNodeDrawLineToChildNode() for usage by custom widgets (#2920) 2025-04-09 12:04:09 +02:00
ocornut
39f34e1e58 TreeNode: Don't latch GetColorU32(ImGuiCol_TreeLines). (#2920)
Some checks are pending
build / Windows (push) Waiting to run
build / Linux (push) Waiting to run
build / MacOS (push) Waiting to run
build / iOS (push) Waiting to run
build / Emscripten (push) Waiting to run
build / Android (push) Waiting to run
Trade off doesn't seem worth it for large trees. User who really needs to alter colors can do it by adjusting Push/Pop locations.
2025-04-08 19:58:59 +02:00
ocornut
e5b218e6d1 TreeNode: added ImGuiTreeNodeFlags_DrawTreeXXX flags. (#2920)
# Conflicts:
#	docs/CHANGELOG.txt
2025-04-08 19:58:59 +02:00
ocornut
faa03031b4 Windows: loosened code to handle ImGuiButtonFlags_FlattenChildren so that master matches docking. (#8554)
Some checks are pending
build / Windows (push) Waiting to run
build / Linux (push) Waiting to run
build / MacOS (push) Waiting to run
build / iOS (push) Waiting to run
build / Emscripten (push) Waiting to run
build / Android (push) Waiting to run
This essentially merges 059560d2 back into master.
2025-04-07 18:21:34 +02:00
ocornut
974bf58a21 Backends: Vulkan: Build and warning fixes. (#8282) 2025-04-07 17:39:00 +02:00
ocornut
91652c317e Backends: Vulkan: Deep-copy ImGui_ImplVulkan_InitInfo::PipelineRenderingCreateInfo's pColorAttachmentFormats buffer when set, in order to reduce common user-error of specifying a pointer to data that gets out of scope. (#8282)
# Conflicts:
#	backends/imgui_impl_vulkan.cpp
#	docs/CHANGELOG.txt
2025-04-07 16:40:14 +02:00
ocornut
9701810bc3 TreeNode: adding ImGuiTreeNodeFlags_NoNavFocus in imgui_internal.h (#8551)
Some checks are pending
build / Windows (push) Waiting to run
build / Linux (push) Waiting to run
build / MacOS (push) Waiting to run
build / iOS (push) Waiting to run
build / Emscripten (push) Waiting to run
build / Android (push) Waiting to run
2025-04-07 11:41:21 +02:00
ocornut
b4bd596a39 Fonts: word-wrapping code handle ideographic comma & full stop (U+3001, U+3002). (#8540)
Some checks failed
build / Windows (push) Has been cancelled
build / Linux (push) Has been cancelled
build / MacOS (push) Has been cancelled
build / iOS (push) Has been cancelled
build / Emscripten (push) Has been cancelled
build / Android (push) Has been cancelled
2025-04-01 22:57:07 +02:00
ocornut
fcab22f80f Fonts: fixed CalcWordWrapPositionA() fallback when width is too small to wrap with multibyte codepoints.. (#8540) 2025-04-01 22:57:07 +02:00
Shixian Sheng
8098d79ca2
Docs: fixed link typo (#8538)
Some checks are pending
build / Windows (push) Waiting to run
build / iOS (push) Waiting to run
build / Emscripten (push) Waiting to run
build / Linux (push) Waiting to run
build / MacOS (push) Waiting to run
build / Android (push) Waiting to run
2025-04-01 09:10:30 +02:00
ocornut
4bdb0ac685 Comments
Some checks are pending
build / Windows (push) Waiting to run
build / Linux (push) Waiting to run
build / MacOS (push) Waiting to run
build / iOS (push) Waiting to run
build / Emscripten (push) Waiting to run
build / Android (push) Waiting to run
2025-03-31 15:12:28 +02:00
ocornut
b6786595a4 Backends: SDLGPU3: Made ImGui_ImplSDLGPU3_PrepareDrawData() reuse GPU Transfer Buffers which were unusually slow to recreate every frame. (#8534) 2025-03-31 14:45:29 +02:00
ocornut
a26fcf58cc Nav: fixed assertion when holding gamepad FaceLeft/West button + pressing a keyboard key. (#8525)
Some checks are pending
build / Windows (push) Waiting to run
build / Linux (push) Waiting to run
build / MacOS (push) Waiting to run
build / iOS (push) Waiting to run
build / Emscripten (push) Waiting to run
build / Android (push) Waiting to run
2025-03-30 16:40:39 +02:00
ocornut
8bbdfefe05 Nav: added bool ConfigNavWindowingWithGamepad to disable windowing with gamepad. (#8525, #4828, #3255, #5641) 2025-03-30 15:05:27 +02:00
ocornut
187acb8609 Nav: polling gamepad for ImGuiKey_NavGamepadMenu use routing-friendly Shortcut() so Ctrl+Tab equivalent may be hijacked. (#8525, #4828, #3255, #5641) 2025-03-30 14:46:58 +02:00
Green Sky
5c9fb8f064 Backends: SDL3: Update for API changes: Revert SDL_GetClipboardText() memory ownership change. (#8530, #7801)
see https://github.com/libsdl-org/SDL/pull/10390
2025-03-30 13:52:39 +02:00
gan74
7674cbc9b2 Added extra operators to ImVec4. (#8510)
Some checks failed
build / Windows (push) Has been cancelled
build / Linux (push) Has been cancelled
build / MacOS (push) Has been cancelled
build / iOS (push) Has been cancelled
build / Emscripten (push) Has been cancelled
build / Android (push) Has been cancelled
2025-03-23 13:09:14 +01:00
ocornut
dbd9ae287a Windows: fixed SetNextWindowCollapsed()/SetWindowCollapsed() breaking codepath that preserve last contents size when collapsed. (#7691) 2025-03-23 12:57:14 +01:00
ocornut
702a67807b Move Changelog entry. (#8509) 2025-03-21 20:17:49 +01:00
puugz
a806d2f9b8 Backends: SDLGPU: Fixed typo in function name Imgui_ImplSDLGPU3_PrepareDrawData() -> ImGui_ImplSDLGPU3_PrepareDrawData(). (#8509, 8163, #7998, #7988) 2025-03-21 20:16:56 +01:00
ocornut
ca3ba28768 Internals: made MousePos an argument of UpdateHoveredWindowAndCaptureFlags(). (#8431, #1152) 2025-03-21 17:21:45 +01:00
tanksdude
f5003aff69
Docs: Fix some typos (#8505) 2025-03-21 16:23:09 +01:00
ocornut
102f3f3a0d IO: variations in analog-only components of gamepad events do not interfere with trickling of mouse position events (#4921, #8508) 2025-03-21 16:18:36 +01:00
ocornut
979c7d76ab Backends: SDL2, SDL3, OSX: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set. (#8508) 2025-03-21 15:42:47 +01:00
ocornut
d467950a5e Style, InputText: added ImGuiCol_InputTextCursor to configure color of the InputText cursor/caret. (#7031) 2025-03-19 17:50:40 +01:00
ocornut
0ecb2bbe74 Version 1.92.0 WIP 2025-03-19 17:45:20 +01:00
ocornut
ee48ffe021 Added comments about line/rect thickness needing scaling. (#7031) 2025-03-19 17:42:19 +01:00
ocornut
5679de60c5 Error Handling: added better report and recovery for extraneous EndPopup() call. (#1651, #8499) 2025-03-18 17:35:43 +01:00
27 changed files with 440 additions and 204 deletions

View file

@ -6,7 +6,7 @@
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
// Missing features or Issues:
// [ ] Platform: Clipboard support.
// [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [ ] Platform: Gamepad support.
// [ ] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
// Important:
// - Consider using SDL or GLFW backend on Android, which will be more full-featured than this.

View file

@ -6,7 +6,7 @@
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
// Missing features or Issues:
// [ ] Platform: Clipboard support.
// [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [ ] Platform: Gamepad support.
// [ ] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
// Important:
// - Consider using SDL or GLFW backend on Android, which will be more full-featured than this.

View file

@ -789,7 +789,7 @@ static inline float Saturate(float v) { return v < 0.0f ? 0.0f : v > 1.0f ? 1.0
static void ImGui_ImplGlfw_UpdateGamepads()
{
ImGuiIO& io = ImGui::GetIO();
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs, but see #8075
return;
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;

View file

@ -7,7 +7,7 @@
// [X] Platform: Clipboard support is part of core Dear ImGui (no specific code in this backend).
// [X] Platform: Mouse support. Can discriminate Mouse/Pen.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy kVK_* values are obsolete since 1.87 and not supported since 1.91.5]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Gamepad support.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: IME support.
// Missing features or Issues:

View file

@ -7,7 +7,7 @@
// [X] Platform: Clipboard support is part of core Dear ImGui (no specific code in this backend).
// [X] Platform: Mouse support. Can discriminate Mouse/Pen.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy kVK_* values are obsolete since 1.87 and not supported since 1.91.5]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Gamepad support.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: IME support.
// Missing features or Issues:
@ -31,6 +31,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set.
// 2025-01-20: Removed notification observer when shutting down. (#8331)
// 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO:
// - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn
@ -536,7 +537,7 @@ static void ImGui_ImplOSX_UpdateMouseCursor()
else
{
NSCursor* desired = bd->MouseCursors[imgui_cursor] ?: bd->MouseCursors[ImGuiMouseCursor_Arrow];
// -[NSCursor set] generates measureable overhead if called unconditionally.
// -[NSCursor set] generates measurable overhead if called unconditionally.
if (desired != NSCursor.currentCursor)
{
[desired set];
@ -552,8 +553,6 @@ static void ImGui_ImplOSX_UpdateMouseCursor()
static void ImGui_ImplOSX_UpdateGamepads()
{
ImGuiIO& io = ImGui::GetIO();
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
return;
#if APPLE_HAS_CONTROLLER
GCController* controller = GCController.current;

View file

@ -7,7 +7,7 @@
// [X] Platform: Clipboard support.
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Gamepad support.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Basic IME support. App needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!.
@ -21,6 +21,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-04-09: Don't attempt to call SDL_CaptureMouse() on drivers where we don't call SDL_GetGlobalMouseState(). (#8561)
// 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set.
// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468)
// 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.
@ -141,6 +143,7 @@ struct ImGui_ImplSDL2_Data
SDL_Cursor* MouseLastCursor;
int MouseLastLeaveFrame;
bool MouseCanUseGlobalState;
bool MouseCanUseCapture;
// Gamepad handling
ImVector<SDL_GameController*> Gamepads;
@ -473,17 +476,6 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
// Check and store if we are on a SDL backend that supports global mouse position
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
bool mouse_can_use_global_state = false;
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
const char* sdl_backend = SDL_GetCurrentVideoDriver();
const char* global_mouse_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
for (int n = 0; n < IM_ARRAYSIZE(global_mouse_whitelist); n++)
if (strncmp(sdl_backend, global_mouse_whitelist[n], strlen(global_mouse_whitelist[n])) == 0)
mouse_can_use_global_state = true;
#endif
// Setup backend capabilities flags
ImGui_ImplSDL2_Data* bd = IM_NEW(ImGui_ImplSDL2_Data)();
io.BackendPlatformUserData = (void*)bd;
@ -494,7 +486,18 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void
bd->Window = window;
bd->WindowID = SDL_GetWindowID(window);
bd->Renderer = renderer;
bd->MouseCanUseGlobalState = mouse_can_use_global_state;
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
bd->MouseCanUseGlobalState = false;
bd->MouseCanUseCapture = false;
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
const char* sdl_backend = SDL_GetCurrentVideoDriver();
const char* capture_and_global_state_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
for (const char* item : capture_and_global_state_whitelist)
if (strncmp(sdl_backend, item, strlen(item)) == 0)
bd->MouseCanUseGlobalState = bd->MouseCanUseCapture = true;
#endif
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText;
@ -629,12 +632,15 @@ 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 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);
// - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to mitigate the issue we wait until mouse has moved to begin capture.
if (bd->MouseCanUseCapture)
{
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);
@ -755,9 +761,6 @@ static void ImGui_ImplSDL2_UpdateGamepads()
bd->WantUpdateGamepadsList = false;
}
// FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
return;
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
if (bd->Gamepads.Size == 0)
return;

View file

@ -6,7 +6,7 @@
// [X] Platform: Clipboard support.
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Gamepad support.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Basic IME support. App needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!.

View file

@ -6,7 +6,7 @@
// [X] Platform: Clipboard support.
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Gamepad support.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: IME support.
@ -20,6 +20,9 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-04-09: Don't attempt to call SDL_CaptureMouse() on drivers where we don't call SDL_GetGlobalMouseState(). (#8561)
// 2025-03-30: Update for SDL3 api changes: Revert SDL_GetClipboardText() memory ownership change. (#8530, #7801)
// 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set.
// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468)
// 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.
@ -108,6 +111,7 @@ struct ImGui_ImplSDL3_Data
SDL_Cursor* MouseLastCursor;
int MousePendingLeaveFrame;
bool MouseCanUseGlobalState;
bool MouseCanUseCapture;
// Gamepad handling
ImVector<SDL_Gamepad*> Gamepads;
@ -132,8 +136,7 @@ static const char* ImGui_ImplSDL3_GetClipboardText(ImGuiContext*)
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
if (bd->ClipboardTextData)
SDL_free(bd->ClipboardTextData);
const char* sdl_clipboard_text = SDL_GetClipboardText();
bd->ClipboardTextData = sdl_clipboard_text ? SDL_strdup(sdl_clipboard_text) : nullptr;
bd->ClipboardTextData = SDL_GetClipboardText();
return bd->ClipboardTextData;
}
@ -460,17 +463,6 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
IM_UNUSED(sdl_gl_context); // Unused in this branch
// Check and store if we are on a SDL backend that supports global mouse position
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
bool mouse_can_use_global_state = false;
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
const char* sdl_backend = SDL_GetCurrentVideoDriver();
const char* global_mouse_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
for (int n = 0; n < IM_ARRAYSIZE(global_mouse_whitelist); n++)
if (strncmp(sdl_backend, global_mouse_whitelist[n], strlen(global_mouse_whitelist[n])) == 0)
mouse_can_use_global_state = true;
#endif
// Setup backend capabilities flags
ImGui_ImplSDL3_Data* bd = IM_NEW(ImGui_ImplSDL3_Data)();
io.BackendPlatformUserData = (void*)bd;
@ -481,7 +473,18 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
bd->Window = window;
bd->WindowID = SDL_GetWindowID(window);
bd->Renderer = renderer;
bd->MouseCanUseGlobalState = mouse_can_use_global_state;
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
bd->MouseCanUseGlobalState = false;
bd->MouseCanUseCapture = false;
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
const char* sdl_backend = SDL_GetCurrentVideoDriver();
const char* capture_and_global_state_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
for (const char* item : capture_and_global_state_whitelist)
if (strncmp(sdl_backend, item, strlen(item)) == 0)
bd->MouseCanUseGlobalState = bd->MouseCanUseCapture = true;
#endif
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL3_SetClipboardText;
@ -595,12 +598,15 @@ 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 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);
// - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to mitigate the issue we wait until mouse has moved to begin capture.
if (bd->MouseCanUseCapture)
{
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);
@ -724,9 +730,6 @@ static void ImGui_ImplSDL3_UpdateGamepads()
SDL_free(sdl_gamepads);
}
// FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
return;
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
if (bd->Gamepads.Size == 0)
return;

View file

@ -6,7 +6,7 @@
// [X] Platform: Clipboard support.
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Gamepad support.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: IME support.

View file

@ -17,10 +17,12 @@
// - Introduction, links and more at the top of imgui.cpp
// Important note to the reader who wish to integrate imgui_impl_sdlgpu3.cpp/.h in their own engine/app.
// - Unlike other backends, the user must call the function Imgui_ImplSDLGPU3_PrepareDrawData() BEFORE issuing a SDL_GPURenderPass containing ImGui_ImplSDLGPU3_RenderDrawData.
// - Unlike other backends, the user must call the function ImGui_ImplSDLGPU3_PrepareDrawData() BEFORE issuing a SDL_GPURenderPass containing ImGui_ImplSDLGPU3_RenderDrawData.
// Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info.
// CHANGELOG
// 2025-03-30: Made ImGui_ImplSDLGPU3_PrepareDrawData() reuse GPU Transfer Buffers which were unusually slow to recreate every frame. Much faster now.
// 2025-03-21: Fixed typo in function name Imgui_ImplSDLGPU3_PrepareDrawData() -> ImGui_ImplSDLGPU3_PrepareDrawData().
// 2025-01-16: Renamed ImGui_ImplSDLGPU3_InitInfo::GpuDevice to Device.
// 2025-01-09: SDL_GPU: Added the SDL_GPU3 backend.
@ -34,10 +36,12 @@
// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplSDLGPU3_RenderDrawData()
struct ImGui_ImplSDLGPU3_FrameData
{
SDL_GPUBuffer* VertexBuffer = nullptr;
SDL_GPUBuffer* IndexBuffer = nullptr;
uint32_t VertexBufferSize = 0;
uint32_t IndexBufferSize = 0;
SDL_GPUBuffer* VertexBuffer = nullptr;
SDL_GPUTransferBuffer* VertexTransferBuffer = nullptr;
uint32_t VertexBufferSize = 0;
SDL_GPUBuffer* IndexBuffer = nullptr;
SDL_GPUTransferBuffer* IndexTransferBuffer = nullptr;
uint32_t IndexBufferSize = 0;
};
struct ImGui_ImplSDLGPU3_Data
@ -113,14 +117,15 @@ static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, SDL_GPUGra
SDL_PushGPUVertexUniformData(command_buffer, 0, &ubo, sizeof(UBO));
}
static void CreateOrResizeBuffer(SDL_GPUBuffer** buffer, uint32_t* old_size, uint32_t new_size, SDL_GPUBufferUsageFlags usage)
static void CreateOrResizeBuffers(SDL_GPUBuffer** buffer, SDL_GPUTransferBuffer** transferbuffer, uint32_t* old_size, uint32_t new_size, SDL_GPUBufferUsageFlags usage)
{
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo;
// Even though this is fairly rarely called.
// FIXME-OPT: Not optimal, but this is fairly rarely called.
SDL_WaitForGPUIdle(v->Device);
SDL_ReleaseGPUBuffer(v->Device, *buffer);
SDL_ReleaseGPUTransferBuffer(v->Device, *transferbuffer);
SDL_GPUBufferCreateInfo buffer_info = {};
buffer_info.usage = usage;
@ -129,12 +134,18 @@ static void CreateOrResizeBuffer(SDL_GPUBuffer** buffer, uint32_t* old_size, uin
*buffer = SDL_CreateGPUBuffer(v->Device, &buffer_info);
*old_size = new_size;
IM_ASSERT(*buffer != nullptr && "Failed to create GPU Buffer, call SDL_GetError() for more information");
SDL_GPUTransferBufferCreateInfo transferbuffer_info = {};
transferbuffer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
transferbuffer_info.size = new_size;
*transferbuffer = SDL_CreateGPUTransferBuffer(v->Device, &transferbuffer_info);
IM_ASSERT(*transferbuffer != nullptr && "Failed to create GPU Transfer Buffer, call SDL_GetError() for more information");
}
// SDL_GPU doesn't allow copy passes to occur while a render or compute pass is bound!
// The only way to allow a user to supply their own RenderPass (to render to a texture instead of the window for example),
// is to split the upload part of ImGui_ImplSDLGPU3_RenderDrawData() to another function that needs to be called by the user before rendering.
void Imgui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer)
void ImGui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
@ -149,25 +160,12 @@ void Imgui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuff
uint32_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert);
uint32_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx);
if (fd->VertexBuffer == nullptr || fd->VertexBufferSize < vertex_size)
CreateOrResizeBuffer(&fd->VertexBuffer, &fd->VertexBufferSize, vertex_size, SDL_GPU_BUFFERUSAGE_VERTEX);
CreateOrResizeBuffers(&fd->VertexBuffer, &fd->VertexTransferBuffer, &fd->VertexBufferSize, vertex_size, SDL_GPU_BUFFERUSAGE_VERTEX);
if (fd->IndexBuffer == nullptr || fd->IndexBufferSize < index_size)
CreateOrResizeBuffer(&fd->IndexBuffer, &fd->IndexBufferSize, index_size, SDL_GPU_BUFFERUSAGE_INDEX);
CreateOrResizeBuffers(&fd->IndexBuffer, &fd->IndexTransferBuffer, &fd->IndexBufferSize, index_size, SDL_GPU_BUFFERUSAGE_INDEX);
// FIXME: It feels like more code could be shared there.
SDL_GPUTransferBufferCreateInfo vertex_transferbuffer_info = {};
vertex_transferbuffer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
vertex_transferbuffer_info.size = vertex_size;
SDL_GPUTransferBufferCreateInfo index_transferbuffer_info = {};
index_transferbuffer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
index_transferbuffer_info.size = index_size;
SDL_GPUTransferBuffer* vertex_transferbuffer = SDL_CreateGPUTransferBuffer(v->Device, &vertex_transferbuffer_info);
IM_ASSERT(vertex_transferbuffer != nullptr && "Failed to create the vertex transfer buffer, call SDL_GetError() for more information");
SDL_GPUTransferBuffer* index_transferbuffer = SDL_CreateGPUTransferBuffer(v->Device, &index_transferbuffer_info);
IM_ASSERT(index_transferbuffer != nullptr && "Failed to create the index transfer buffer, call SDL_GetError() for more information");
ImDrawVert* vtx_dst = (ImDrawVert*)SDL_MapGPUTransferBuffer(v->Device, vertex_transferbuffer, true);
ImDrawIdx* idx_dst = (ImDrawIdx*)SDL_MapGPUTransferBuffer(v->Device, index_transferbuffer, true);
ImDrawVert* vtx_dst = (ImDrawVert*)SDL_MapGPUTransferBuffer(v->Device, fd->VertexTransferBuffer, true);
ImDrawIdx* idx_dst = (ImDrawIdx*)SDL_MapGPUTransferBuffer(v->Device, fd->IndexTransferBuffer, true);
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
@ -176,15 +174,15 @@ void Imgui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuff
vtx_dst += draw_list->VtxBuffer.Size;
idx_dst += draw_list->IdxBuffer.Size;
}
SDL_UnmapGPUTransferBuffer(v->Device, vertex_transferbuffer);
SDL_UnmapGPUTransferBuffer(v->Device, index_transferbuffer);
SDL_UnmapGPUTransferBuffer(v->Device, fd->VertexTransferBuffer);
SDL_UnmapGPUTransferBuffer(v->Device, fd->IndexTransferBuffer);
SDL_GPUTransferBufferLocation vertex_buffer_location = {};
vertex_buffer_location.offset = 0;
vertex_buffer_location.transfer_buffer = vertex_transferbuffer;
vertex_buffer_location.transfer_buffer = fd->VertexTransferBuffer;
SDL_GPUTransferBufferLocation index_buffer_location = {};
index_buffer_location.offset = 0;
index_buffer_location.transfer_buffer = index_transferbuffer;
index_buffer_location.transfer_buffer = fd->IndexTransferBuffer;
SDL_GPUBufferRegion vertex_buffer_region = {};
vertex_buffer_region.buffer = fd->VertexBuffer;
@ -200,8 +198,6 @@ void Imgui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuff
SDL_UploadToGPUBuffer(copy_pass, &vertex_buffer_location, &vertex_buffer_region, true);
SDL_UploadToGPUBuffer(copy_pass, &index_buffer_location, &index_buffer_region, true);
SDL_EndGPUCopyPass(copy_pass);
SDL_ReleaseGPUTransferBuffer(v->Device, index_transferbuffer);
SDL_ReleaseGPUTransferBuffer(v->Device, vertex_transferbuffer);
}
void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline)
@ -366,7 +362,7 @@ void ImGui_ImplSDLGPU3_DestroyFontsTexture()
io.Fonts->SetTexID(0);
}
static void Imgui_ImplSDLGPU3_CreateShaders()
static void ImGui_ImplSDLGPU3_CreateShaders()
{
// Create the shader modules
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
@ -431,7 +427,7 @@ static void ImGui_ImplSDLGPU3_CreateGraphicsPipeline()
{
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo;
Imgui_ImplSDLGPU3_CreateShaders();
ImGui_ImplSDLGPU3_CreateShaders();
SDL_GPUVertexBufferDescription vertex_buffer_desc[1];
vertex_buffer_desc[0].slot = 0;
@ -546,12 +542,14 @@ void ImGui_ImplSDLGPU3_DestroyFrameData()
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo;
SDL_ReleaseGPUBuffer(v->Device, bd->MainWindowFrameData.VertexBuffer);
SDL_ReleaseGPUBuffer(v->Device, bd->MainWindowFrameData.IndexBuffer);
bd->MainWindowFrameData.VertexBuffer = nullptr;
bd->MainWindowFrameData.IndexBuffer = nullptr;
bd->MainWindowFrameData.VertexBufferSize = 0;
bd->MainWindowFrameData.IndexBufferSize = 0;
ImGui_ImplSDLGPU3_FrameData* fd = &bd->MainWindowFrameData;
SDL_ReleaseGPUBuffer(v->Device, fd->VertexBuffer);
SDL_ReleaseGPUBuffer(v->Device, fd->IndexBuffer);
SDL_ReleaseGPUTransferBuffer(v->Device, fd->VertexTransferBuffer);
SDL_ReleaseGPUTransferBuffer(v->Device, fd->IndexTransferBuffer);
fd->VertexBuffer = fd->IndexBuffer = nullptr;
fd->VertexTransferBuffer = fd->IndexTransferBuffer = nullptr;
fd->VertexBufferSize = fd->IndexBufferSize = 0;
}
void ImGui_ImplSDLGPU3_DestroyDeviceObjects()

View file

@ -17,7 +17,7 @@
// - Introduction, links and more at the top of imgui.cpp
// Important note to the reader who wish to integrate imgui_impl_sdlgpu3.cpp/.h in their own engine/app.
// - Unline other backends, the user must call the function Imgui_ImplSDLGPU_PrepareDrawData BEFORE issuing a SDL_GPURenderPass containing ImGui_ImplSDLGPU_RenderDrawData.
// - Unlike other backends, the user must call the function ImGui_ImplSDLGPU_PrepareDrawData BEFORE issuing a SDL_GPURenderPass containing ImGui_ImplSDLGPU_RenderDrawData.
// Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info.
#pragma once
@ -38,7 +38,7 @@ struct ImGui_ImplSDLGPU3_InitInfo
IMGUI_IMPL_API bool ImGui_ImplSDLGPU3_Init(ImGui_ImplSDLGPU3_InitInfo* info);
IMGUI_IMPL_API void ImGui_ImplSDLGPU3_Shutdown();
IMGUI_IMPL_API void ImGui_ImplSDLGPU3_NewFrame();
IMGUI_IMPL_API void Imgui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer);
IMGUI_IMPL_API void ImGui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer);
IMGUI_IMPL_API void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline = nullptr);
IMGUI_IMPL_API void ImGui_ImplSDLGPU3_CreateDeviceObjects();

View file

@ -26,6 +26,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-04-07: Vulkan: Deep-copy ImGui_ImplVulkan_InitInfo::PipelineRenderingCreateInfo's pColorAttachmentFormats buffer when set, in order to reduce common user-error of specifying a pointer to data that gets out of scope. (#8282)
// 2025-02-14: *BREAKING CHANGE*: Added uint32_t api_version to ImGui_ImplVulkan_LoadFunctions().
// 2025-02-13: Vulkan: Added ApiVersion field in ImGui_ImplVulkan_InitInfo. Default to header version if unspecified. Dynamic rendering path loads "vkCmdBeginRendering/vkCmdEndRendering" (without -KHR suffix) on API 1.3. (#8326)
// 2025-01-09: Vulkan: Added IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE to clarify how many image sampler descriptors are expected to be available in descriptor pool. (#6642)
@ -1174,6 +1175,16 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)
IM_ASSERT(info->RenderPass != VK_NULL_HANDLE);
bd->VulkanInitInfo = *info;
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
if (v->PipelineRenderingCreateInfo.pColorAttachmentFormats != NULL)
{
// Deep copy buffer to reduce error-rate for end user (#8282)
VkFormat* formats_copy = (VkFormat*)IM_ALLOC(sizeof(VkFormat) * v->PipelineRenderingCreateInfo.colorAttachmentCount);
memcpy(formats_copy, v->PipelineRenderingCreateInfo.pColorAttachmentFormats, sizeof(VkFormat) * v->PipelineRenderingCreateInfo.colorAttachmentCount);
v->PipelineRenderingCreateInfo.pColorAttachmentFormats = formats_copy;
}
#endif
ImGui_ImplVulkan_CreateDeviceObjects();
@ -1187,6 +1198,10 @@ void ImGui_ImplVulkan_Shutdown()
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplVulkan_DestroyDeviceObjects();
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
IM_FREE((void*)bd->VulkanInitInfo.PipelineRenderingCreateInfo.pColorAttachmentFormats);
#endif
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset;

View file

@ -5,7 +5,7 @@
// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values are obsolete since 1.87 and not supported since 1.91.5]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Gamepad support.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
@ -335,8 +335,6 @@ static void ImGui_ImplWin32_UpdateGamepads(ImGuiIO& io)
{
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(io);
//if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
// return;
// Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow.
// Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE.

View file

@ -5,7 +5,7 @@
// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values are obsolete since 1.87 and not supported since 1.91.5]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Gamepad support.
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.

View file

@ -35,6 +35,64 @@ 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.92.0 WIP (In Progress)
-----------------------------------------------------------------------
Breaking changes:
- Backends: SDL3: Fixed casing typo in function name: (#8509, #8163, #7998, #7988) [@puugz]
- Imgui_ImplSDLGPU3_PrepareDrawData() -> ImGui_ImplSDLGPU3_PrepareDrawData()
Other changes:
- IO: variations in analog-only components of gamepad events do not interfere
with trickling of mouse position events (#4921, #8508)
- Windows: fixed SetNextWindowCollapsed()/SetWindowCollapsed() breaking
codepath that preserve last contents size when collapsed, resulting in
programmatically uncollapsing auto-sizing windows having them flicker size
for a frame. (#7691) [@achabense]
- Windows: loosened code to allow hovering of resize grips, borders, and table
borders while hovering a sibling child window, so that the code in master matches
one in docking (they accidentally diverged). (#8554)
- TreeNode: added flags to draw tree hierarchy outlines linking parent
and tree nodes: (#2920)
- ImGuiTreeNodeFlags_DrawLinesNone: No lines drawn (default value in style.TreeLinesFlags).
- ImGuiTreeNodeFlags_DrawLinesFull: Horizontal lines to child nodes. Vertical line drawn down to TreePop() position: cover full contents.
- ImGuiTreeNodeFlags_DrawLinesToNodes: Horizontal lines to child nodes. Vertical line drawn down to bottom-most child node.
- Added style.TreeLinesFlags which stores the default setting,
which may be overriden in individual TreeNode() calls.
- Added style.TreeLinesSize (default to 1.0f).
- Added ImGuiCol_TreeLines (in default style this is the same as ImGuiCol_Border).
- Caveats:
- Tree nodes may be used in many creative ways (manually positioning openable
nodes in unusual ways, using indent to create tree-looking structures, etc.)
and the feature may not accurately represent them in every cases.
- The feature adds a little cost as extra data needs to be stored.
- Nav: fixed assertion when holding gamepad FaceLeft/West button to open
CTRL+Tab windowing + pressing a keyboard key. (#8525)
- Error Handling: added better error report and recovery for extraneous
EndPopup() call. (#1651, #8499)
- Fonts: word-wrapping code handle ideographic comma & full stop (U+3001, U+3002). (#8540)
- Fonts: fixed CalcWordWrapPositionA() fallback when width is too small to wrap:
would use a +1 offset instead of advancing to the next UTF-8 codepoint. (#8540)
- Style, InputText: added ImGuiCol_InputTextCursor to configure color of
the InputText cursor/caret. (#7031)
- Misc: added extra operators to ImVec4 in IMGUI_DEFINE_MATH_OPERATORS block. (#8510) [@gan74]
- Backends: SDL2, SDL3, OSX: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad
regardless of ImGuiConfigFlags_NavEnableGamepad being set. (#8508)
- Backends: SDL2, SDL3: don't attempt to call SDL_CaptureMouse() on drivers where we don't
call SDL_GetGlobalMouseState(). This is specifically for Wayland but we currently use
the same white-list as SDL_GetGlobalMouseState(). (#8561) [@vs49688]
- Backends: SDL3: Update for SDL3 api changes: revert SDL_GetClipboardText()
memory ownership change. (#8530, #7801) [@Green-Sky]
- Backends: SDLGPU3: Made ImGui_ImplSDLGPU3_PrepareDrawData() reuse GPU Transfer Buffers which
were unusually slow to recreate every frame. Much faster now. (#8534) [@ocornut, @TheMode]
- Backends: Vulkan: Deep-copy ImGui_ImplVulkan_InitInfo::PipelineRenderingCreateInfo's
pColorAttachmentFormats buffer when set, in order to reduce common user-error of
specifying a pointer to data that gets out of scope. (#8282)
-----------------------------------------------------------------------
VERSION 1.91.9b (Released 2025-03-17)
-----------------------------------------------------------------------
@ -498,7 +556,7 @@ Other changes:
- Set io.ConfigNavCursorVisibleAuto = true (default) to enable automatic toggling
of cursor visibility (mouse click hide the cursor, arrow keys makes it visible).
- Set io.ConfigNavCursorVisibleAlways to keep cursor always visible.
- Nav: added NavSetCursorVisible(bool visible) function to manipulate visibility of
- Nav: added SetNavCursorVisible(bool visible) function to manipulate visibility of
navigation cursor (e.g. set default state, or after some actions). (#1074, #2048, #7237, #8059)
- Nav: added io.ConfigNavEscapeClearFocusItem and io.ConfigNavEscapeClearFocusWindow to change
how pressing Escape affects navigation. (#8059, #2048, #1074, #3200)
@ -615,7 +673,7 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
Breaking changes:
- Internals: using multiple overlayed ButtonBehavior() with same ID will now have the
- Internals: using multiple overlaid ButtonBehavior() with same ID will now have the
io.ConfigDebugHighlightIdConflicts=true feature emit a warning. (#8030)
It was one of the rare case where using same ID is legal. Workarounds:
- use single ButtonBehavior() call with multiple _MouseButton flags

View file

@ -58,7 +58,7 @@ Allegro 5 example. <BR>
Android + OpenGL3 (ES) example. <BR>
= main.cpp + imgui_impl_android.cpp + imgui_impl_opengl3.cpp
[example_apple_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_metal/) <BR>
[example_apple_metal/](https://github.com/ocornut/imgui/tree/master/examples/example_apple_metal/) <BR>
OSX & iOS + Metal example. <BR>
= main.m + imgui_impl_osx.mm + imgui_impl_metal.mm <BR>
It is based on the "cross-platform" game template provided with Xcode as of Xcode 9.

View file

@ -7,7 +7,7 @@
// - Introduction, links and more at the top of imgui.cpp
// Important note to the reader who wish to integrate imgui_impl_sdlgpu3.cpp/.h in their own engine/app.
// - Unlike other backends, the user must call the function Imgui_ImplSDLGPU_PrepareDrawData() BEFORE issuing a SDL_GPURenderPass containing ImGui_ImplSDLGPU_RenderDrawData.
// - Unlike other backends, the user must call the function ImGui_ImplSDLGPU_PrepareDrawData() BEFORE issuing a SDL_GPURenderPass containing ImGui_ImplSDLGPU_RenderDrawData.
// Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info.
#include "imgui.h"
@ -178,8 +178,8 @@ int main(int, char**)
if (swapchain_texture != nullptr && !is_minimized)
{
// This is mandatory: call Imgui_ImplSDLGPU3_PrepareDrawData() to upload the vertex/index buffer!
Imgui_ImplSDLGPU3_PrepareDrawData(draw_data, command_buffer);
// This is mandatory: call ImGui_ImplSDLGPU3_PrepareDrawData() to upload the vertex/index buffer!
ImGui_ImplSDLGPU3_PrepareDrawData(draw_data, command_buffer);
// Setup and start a render pass
SDL_GPUColorTargetInfo target_info = {};

View file

@ -336,7 +336,7 @@ typedef struct
uSynergyJoystickCallback m_joystickCallback; /* Callback for joystick events */
uSynergyClipboardCallback m_clipboardCallback; /* Callback for clipboard events */
/* State data, used internall by client, initialized by uSynergyInit() */
/* State data, used internally by client, initialized by uSynergyInit() */
uSynergyBool m_connected; /* Is our socket connected? */
uSynergyBool m_hasReceivedHello; /* Have we received a 'Hello' from the server? */
uSynergyBool m_isCaptured; /* Is Synergy active (i.e. this client is receiving input messages?) */

108
imgui.cpp
View file

@ -1,4 +1,4 @@
// dear imgui, v1.91.9b
// dear imgui, v1.92.0 WIP
// (main code and documentation)
// Help:
@ -477,7 +477,7 @@ CODE
- 2024/10/03 (1.91.3) - drags: treat v_min==v_max as a valid clamping range when != 0.0f. Zero is a still special value due to legacy reasons, unless using ImGuiSliderFlags_ClampZeroRange. (#7968, #3361, #76)
- drags: extended behavior of ImGuiSliderFlags_AlwaysClamp to include _ClampZeroRange. It considers v_min==v_max==0.0f as a valid clamping range (aka edits not allowed).
although unlikely, it you wish to only clamp on text input but want v_min==v_max==0.0f to mean unclamped drags, you can use _ClampOnInput instead of _AlwaysClamp. (#7968, #3361, #76)
- 2024/09/10 (1.91.2) - internals: using multiple overlayed ButtonBehavior() with same ID will now have io.ConfigDebugHighlightIdConflicts=true feature emit a warning. (#8030)
- 2024/09/10 (1.91.2) - internals: using multiple overlaid ButtonBehavior() with same ID will now have io.ConfigDebugHighlightIdConflicts=true feature emit a warning. (#8030)
it was one of the rare case where using same ID is legal. workarounds: (1) use single ButtonBehavior() call with multiple _MouseButton flags, or (2) surround the calls with PushItemFlag(ImGuiItemFlags_AllowDuplicateId, true); ... PopItemFlag()
- 2024/08/23 (1.91.1) - renamed ImGuiChildFlags_Border to ImGuiChildFlags_Borders for consistency. kept inline redirection flag.
- 2024/08/22 (1.91.1) - moved some functions from ImGuiIO to ImGuiPlatformIO structure:
@ -667,7 +667,7 @@ CODE
- 2022/01/10 (1.87) - inputs: reworked keyboard IO. Removed io.KeyMap[], io.KeysDown[] in favor of calling io.AddKeyEvent(), ImGui::IsKeyDown(). Removed GetKeyIndex(), now unnecessary. All IsKeyXXX() functions now take ImGuiKey values. All features are still functional until IMGUI_DISABLE_OBSOLETE_KEYIO is defined. Read Changelog and Release Notes for details.
- IsKeyPressed(MY_NATIVE_KEY_XXX) -> use IsKeyPressed(ImGuiKey_XXX)
- IsKeyPressed(GetKeyIndex(ImGuiKey_XXX)) -> use IsKeyPressed(ImGuiKey_XXX)
- Backend writing to io.KeyMap[],io.KeysDown[] -> backend should call io.AddKeyEvent() (+ call io.SetKeyEventNativeData() if you want legacy user code to stil function with legacy key codes).
- Backend writing to io.KeyMap[],io.KeysDown[] -> backend should call io.AddKeyEvent() (+ call io.SetKeyEventNativeData() if you want legacy user code to still function with legacy key codes).
- Backend writing to io.KeyCtrl, io.KeyShift.. -> backend should call io.AddKeyEvent() with ImGuiMod_XXX values. *IF YOU PULLED CODE BETWEEN 2021/01/10 and 2021/01/27: We used to have a io.AddKeyModsEvent() function which was now replaced by io.AddKeyEvent() with ImGuiMod_XXX values.*
- one case won't work with backward compatibility: if your custom backend used ImGuiKey as mock native indices (e.g. "io.KeyMap[ImGuiKey_A] = ImGuiKey_A") because those values are now larger than the legacy KeyDown[] array. Will assert.
- inputs: added ImGuiKey_ModCtrl/ImGuiKey_ModShift/ImGuiKey_ModAlt/ImGuiKey_ModSuper values to submit keyboard modifiers using io.AddKeyEvent(), instead of writing directly to io.KeyCtrl, io.KeyShift, io.KeyAlt, io.KeySuper.
@ -876,7 +876,7 @@ CODE
- renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete).
- renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete).
- 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency.
- 2017/08/20 (1.51) - added PushStyleColor(ImGuiCol idx, ImU32 col) overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix.
- 2017/08/20 (1.51) - added PushStyleColor(ImGuiCol idx, ImU32 col) overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicitly to fix.
- 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame type.
- 2017/08/15 (1.51) - changed parameter order for BeginPopupContextWindow() from (const char*,int buttons,bool also_over_items) to (const char*,int buttons,bool also_over_items). Note that most calls relied on default parameters completely.
- 2017/08/13 (1.51) - renamed ImGuiCol_Column to ImGuiCol_Separator, ImGuiCol_ColumnHovered to ImGuiCol_SeparatorHovered, ImGuiCol_ColumnActive to ImGuiCol_SeparatorActive. Kept redirection enums (will obsolete).
@ -1360,6 +1360,8 @@ ImGuiStyle::ImGuiStyle()
TabBarOverlineSize = 1.0f; // Thickness of tab-bar overline, which highlights the selected tab-bar.
TableAngledHeadersAngle = 35.0f * (IM_PI / 180.0f); // Angle of angled headers (supported values range from -50 degrees to +50 degrees).
TableAngledHeadersTextAlign = ImVec2(0.5f,0.0f);// Alignment of angled headers within the cell
TreeLinesFlags = ImGuiTreeNodeFlags_DrawLinesNone;
TreeLinesSize = 1.0f; // Thickness of outlines when using ImGuiTreeNodeFlags_DrawLines.
ColorButtonPosition = ImGuiDir_Right; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
SelectableTextAlign = ImVec2(0.0f,0.0f);// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
@ -1748,7 +1750,7 @@ void ImGuiIO::AddMouseButtonEvent(int mouse_button, bool down)
// On MacOS X: Convert Ctrl(Super)+Left click into Right-click: handle held button.
if (ConfigMacOSXBehaviors && mouse_button == 0 && MouseCtrlLeftAsRightClick)
{
// Order of both statements matterns: this event will still release mouse button 1
// Order of both statements matters: this event will still release mouse button 1
mouse_button = 1;
if (!down)
MouseCtrlLeftAsRightClick = false;
@ -3415,6 +3417,7 @@ static const ImGuiStyleVarInfo GStyleVarsInfo[] =
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TabBarOverlineSize) }, // ImGuiStyleVar_TabBarOverlineSize
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersAngle)}, // ImGuiStyleVar_TableAngledHeadersAngle
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersTextAlign)},// ImGuiStyleVar_TableAngledHeadersTextAlign
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TreeLinesSize)}, // ImGuiStyleVar_TreeLinesSize
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorTextBorderSize)}, // ImGuiStyleVar_SeparatorTextBorderSize
@ -3544,6 +3547,7 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx)
case ImGuiCol_ResizeGrip: return "ResizeGrip";
case ImGuiCol_ResizeGripHovered: return "ResizeGripHovered";
case ImGuiCol_ResizeGripActive: return "ResizeGripActive";
case ImGuiCol_InputTextCursor: return "InputTextCursor";
case ImGuiCol_TabHovered: return "TabHovered";
case ImGuiCol_Tab: return "Tab";
case ImGuiCol_TabSelected: return "TabSelected";
@ -3562,6 +3566,7 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx)
case ImGuiCol_TableRowBgAlt: return "TableRowBgAlt";
case ImGuiCol_TextLink: return "TextLink";
case ImGuiCol_TextSelectedBg: return "TextSelectedBg";
case ImGuiCol_TreeLines: return "TreeLines";
case ImGuiCol_DragDropTarget: return "DragDropTarget";
case ImGuiCol_NavCursor: return "NavCursor";
case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight";
@ -3636,7 +3641,7 @@ void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end
// Default clip_rect uses (pos_min,pos_max)
// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges)
// FIXME-OPT: Since we have or calculate text_size we could coarse clip whole block immediately, especally for text above draw_list->DrawList.
// FIXME-OPT: Since we have or calculate text_size we could coarse clip whole block immediately, especially for text above draw_list->DrawList.
// Effectively as this is called from widget doing their own coarse clipping it's not very valuable presently. Next time function will take
// better advantage of the render function taking size into account for coarse clipping.
void ImGui::RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_display_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect)
@ -4015,9 +4020,11 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
// All platforms use Ctrl+Tab but Ctrl<>Super are swapped on Mac...
// FIXME: Because this value is stored, it annoyingly interfere with toggling io.ConfigMacOSXBehaviors updating this..
ConfigNavWindowingWithGamepad = true;
ConfigNavWindowingKeyNext = IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiKey_Tab) : (ImGuiMod_Ctrl | ImGuiKey_Tab);
ConfigNavWindowingKeyPrev = IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiMod_Shift | ImGuiKey_Tab) : (ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab);
NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL;
NavWindowingInputSource = ImGuiInputSource_None;
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
NavWindowingToggleLayer = false;
NavWindowingToggleKey = ImGuiKey_None;
@ -5057,7 +5064,7 @@ static bool IsWindowActiveAndVisible(ImGuiWindow* window)
}
// The reason this is exposed in imgui_internal.h is: on touch-based system that don't have hovering, we want to dispatch inputs to the right target (imgui vs imgui+app)
void ImGui::UpdateHoveredWindowAndCaptureFlags()
void ImGui::UpdateHoveredWindowAndCaptureFlags(const ImVec2& mouse_pos)
{
ImGuiContext& g = *GImGui;
ImGuiIO& io = g.IO;
@ -5071,7 +5078,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
// - When moving a window we can skip the search, which also conveniently bypasses the fact that window->WindowRectClipped is lagging as this point of the frame.
// - We also support the moved window toggling the NoInputs flag after moving has started in order to be able to detect windows below it, which is useful for e.g. docking mechanisms.
bool clear_hovered_windows = false;
FindHoveredWindowEx(g.IO.MousePos, false, &g.HoveredWindow, &g.HoveredWindowUnderMovingWindow);
FindHoveredWindowEx(mouse_pos, false, &g.HoveredWindow, &g.HoveredWindowUnderMovingWindow);
g.HoveredWindowBeforeClear = g.HoveredWindow;
// Modal windows prevents mouse from hovering behind them.
@ -5342,7 +5349,7 @@ void ImGui::NewFrame()
// Find hovered window
// (needs to be before UpdateMouseMovingWindowNewFrame so we fill g.HoveredWindowUnderMovingWindow on the mouse release frame)
// (currently needs to be done after the WasActive=Active loop and FindHoveredWindowEx uses ->Active)
UpdateHoveredWindowAndCaptureFlags();
UpdateHoveredWindowAndCaptureFlags(g.IO.MousePos);
// Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering)
UpdateMouseMovingWindowNewFrame();
@ -5524,7 +5531,7 @@ static void InitViewportDrawData(ImGuiViewportP* viewport)
// - If the code here changes, may need to update code of functions like NextColumn() and PushColumnClipRect():
// some frequently called functions which to modify both channels and clipping simultaneously tend to use the
// more specialized SetWindowClipRectBeforeSetChannel() to avoid extraneous updates of underlying ImDrawCmds.
// - This is analoguous to PushFont()/PopFont() in the sense that are a mixing a global stack and a window stack,
// - This is analogous to PushFont()/PopFont() in the sense that are a mixing a global stack and a window stack,
// which in the case of ClipRect is not so problematic but tends to be more restrictive for fonts.
void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect)
{
@ -5617,7 +5624,7 @@ static void ImGui::RenderDimmedBackgrounds()
if (window->DrawList->CmdBuffer.Size == 0)
window->DrawList->AddDrawCmd();
window->DrawList->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size);
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), window->WindowRounding, 0, 3.0f);
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), window->WindowRounding, 0, 3.0f); // FIXME-DPI
window->DrawList->PopClipRect();
}
}
@ -5716,7 +5723,7 @@ void ImGui::EndFrame()
}
// Prepare the data for rendering so you can call GetDrawData()
// (As with anything within the ImGui:: namspace this doesn't touch your GPU or graphics API at all:
// (As with anything within the ImGui:: namespace this doesn't touch your GPU or graphics API at all:
// it is the role of the ImGui_ImplXXXX_RenderDrawData() function provided by the renderer backend)
void ImGui::Render()
{
@ -7869,7 +7876,7 @@ void ImGui::SetCurrentFont(ImFont* font)
g.DrawListSharedData.FontScale = g.FontScale;
}
// Use ImDrawList::_SetTextureID(), making our shared g.FontStack[] authorative against window-local ImDrawList.
// Use ImDrawList::_SetTextureID(), making our shared g.FontStack[] authoritative against window-local ImDrawList.
// - Whereas ImDrawList::PushTextureID()/PopTextureID() is not to be used across Begin() calls.
// - Note that we don't propagate current texture id when e.g. Begin()-ing into a new window, we never really did...
// - Some code paths never really fully worked with multiple atlas textures.
@ -8227,8 +8234,10 @@ void ImGui::SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond co
return;
window->SetWindowCollapsedAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
// Set
window->Collapsed = collapsed;
// Queue applying in Begin()
if (window->WantCollapseToggle)
window->Collapsed ^= 1;
window->WantCollapseToggle = (window->Collapsed != collapsed);
}
void ImGui::SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size)
@ -9867,12 +9876,16 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
if (trickle_interleaved_nonchar_keys_and_text && (text_inputted && !key_is_potentially_for_char_input))
break;
if (key_data->Down != e->Key.Down) // Analog change only do not trigger this, so it won't block e.g. further mouse pos events testing key_changed.
{
key_changed = true;
key_changed_mask.SetBit(key_data_index);
if (trickle_interleaved_nonchar_keys_and_text && !key_is_potentially_for_char_input)
key_changed_nonchar = true;
}
key_data->Down = e->Key.Down;
key_data->AnalogValue = e->Key.AnalogValue;
key_changed = true;
key_changed_mask.SetBit(key_data_index);
if (trickle_interleaved_nonchar_keys_and_text && !key_is_potentially_for_char_input)
key_changed_nonchar = true;
}
else if (e->Type == ImGuiInputEventType_Text)
{
@ -10234,6 +10247,7 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
IM_ASSERT(g.Style.WindowBorderHoverPadding > 0.0f && "Invalid style setting!"); // Required otherwise cannot resize from borders.
IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
IM_ASSERT(g.Style.ColorButtonPosition == ImGuiDir_Left || g.Style.ColorButtonPosition == ImGuiDir_Right);
IM_ASSERT(g.Style.TreeLinesFlags == ImGuiTreeNodeFlags_DrawLinesNone || g.Style.TreeLinesFlags == ImGuiTreeNodeFlags_DrawLinesFull || g.Style.TreeLinesFlags == ImGuiTreeNodeFlags_DrawLinesToNodes);
// Error handling: we do not accept 100% silent recovery! Please contact me if you feel this is getting in your way.
if (g.IO.ConfigErrorRecovery)
@ -11355,7 +11369,7 @@ bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags ext
// - offset visibility to increase visibility around mouse.
// - never clamp within outer viewport boundary.
// We call SetNextWindowPos() to enforce position and disable clamping.
// See FindBestWindowPosForPopup() for positionning logic of other tooltips (not drag and drop ones).
// See FindBestWindowPosForPopup() for positioning logic of other tooltips (not drag and drop ones).
//ImVec2 tooltip_pos = g.IO.MousePos - g.ActiveIdClickOffset - g.Style.WindowPadding;
const bool is_touchscreen = (g.IO.MouseSource == ImGuiMouseSource_TouchScreen);
if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasPos) == 0)
@ -11818,8 +11832,11 @@ void ImGui::EndPopup()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginPopup()/EndPopup() calls
IM_ASSERT(g.BeginPopupStack.Size > 0);
if ((window->Flags & ImGuiWindowFlags_Popup) == 0 || g.BeginPopupStack.Size == 0)
{
IM_ASSERT_USER_ERROR(0, "Calling EndPopup() too many times or in wrong window!");
return;
}
// Make all menus and popups wrap around for now, may need to expose that policy (e.g. focus scope could include wrap/loop policy flags used by new move requests)
if (g.NavWindow == window)
@ -12782,7 +12799,7 @@ void ImGui::NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result)
}
// Called by TreePop() to implement ImGuiTreeNodeFlags_NavLeftJumpsBackHere
void ImGui::NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiTreeNodeStackData* tree_node_data)
void ImGui::NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, const ImGuiTreeNodeStackData* tree_node_data)
{
ImGuiContext& g = *GImGui;
g.NavMoveScoringItems = false;
@ -13769,17 +13786,18 @@ static void ImGui::NavUpdateWindowing()
const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
const bool keyboard_next_window = allow_windowing && g.ConfigNavWindowingKeyNext && Shortcut(g.ConfigNavWindowingKeyNext, ImGuiInputFlags_Repeat | ImGuiInputFlags_RouteAlways, owner_id);
const bool keyboard_prev_window = allow_windowing && g.ConfigNavWindowingKeyPrev && Shortcut(g.ConfigNavWindowingKeyPrev, ImGuiInputFlags_Repeat | ImGuiInputFlags_RouteAlways, owner_id);
const bool start_windowing_with_gamepad = allow_windowing && nav_gamepad_active && !g.NavWindowingTarget && IsKeyPressed(ImGuiKey_NavGamepadMenu, ImGuiInputFlags_None);
const bool start_windowing_with_gamepad = allow_windowing && nav_gamepad_active && !g.NavWindowingTarget && Shortcut(ImGuiKey_NavGamepadMenu, ImGuiInputFlags_RouteAlways, owner_id);
const bool start_windowing_with_keyboard = allow_windowing && !g.NavWindowingTarget && (keyboard_next_window || keyboard_prev_window); // Note: enabled even without NavEnableKeyboard!
bool just_started_windowing_from_null_focus = false;
if (start_windowing_with_gamepad || start_windowing_with_keyboard)
if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
{
g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow; // Current location
if (start_windowing_with_keyboard || g.ConfigNavWindowingWithGamepad)
g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow; // Current location
g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f;
g.NavWindowingAccumDeltaPos = g.NavWindowingAccumDeltaSize = ImVec2(0.0f, 0.0f);
g.NavWindowingToggleLayer = start_windowing_with_gamepad ? true : false; // Gamepad starts toggling layer
g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad;
g.NavWindowingInputSource = g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad;
if (g.NavWindow == NULL)
just_started_windowing_from_null_focus = true;
@ -13789,18 +13807,22 @@ static void ImGui::NavUpdateWindowing()
}
// Gamepad update
g.NavWindowingTimer += io.DeltaTime;
if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_Gamepad)
if ((g.NavWindowingTarget || g.NavWindowingToggleLayer) && g.NavWindowingInputSource == ImGuiInputSource_Gamepad)
{
// Highlight only appears after a brief time holding the button, so that a fast tap on PadMenu (to toggle NavLayer) doesn't add visual noise
g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f));
// Select window to focus
const int focus_change_dir = (int)IsKeyPressed(ImGuiKey_GamepadL1) - (int)IsKeyPressed(ImGuiKey_GamepadR1);
if (focus_change_dir != 0 && !just_started_windowing_from_null_focus)
if (g.NavWindowingTarget != NULL)
{
NavUpdateWindowingTarget(focus_change_dir);
g.NavWindowingHighlightAlpha = 1.0f;
// Highlight only appears after a brief time holding the button, so that a fast tap on ImGuiKey_NavGamepadMenu (to toggle NavLayer) doesn't add visual noise
// However inputs are accepted immediately, so you press ImGuiKey_NavGamepadMenu + L1/R1 fast.
g.NavWindowingTimer += io.DeltaTime;
g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f));
// Select window to focus
const int focus_change_dir = (int)IsKeyPressed(ImGuiKey_GamepadL1) - (int)IsKeyPressed(ImGuiKey_GamepadR1);
if (focus_change_dir != 0 && !just_started_windowing_from_null_focus)
{
NavUpdateWindowingTarget(focus_change_dir);
g.NavWindowingHighlightAlpha = 1.0f;
}
}
// Single press toggles NavLayer, long press with L/R apply actual focus on release (until then the window was merely rendered top-most)
@ -13812,15 +13834,17 @@ static void ImGui::NavUpdateWindowing()
else if (!g.NavWindowingToggleLayer)
apply_focus_window = g.NavWindowingTarget;
g.NavWindowingTarget = NULL;
g.NavWindowingToggleLayer = false;
}
}
// Keyboard: Focus
if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_Keyboard)
if (g.NavWindowingTarget && g.NavWindowingInputSource == ImGuiInputSource_Keyboard)
{
// Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise
ImGuiKeyChord shared_mods = ((g.ConfigNavWindowingKeyNext ? g.ConfigNavWindowingKeyNext : ImGuiMod_Mask_) & (g.ConfigNavWindowingKeyPrev ? g.ConfigNavWindowingKeyPrev : ImGuiMod_Mask_)) & ImGuiMod_Mask_;
IM_ASSERT(shared_mods != 0); // Next/Prev shortcut currently needs a shared modifier to "hold", otherwise Prev actions would keep cycling between two windows.
g.NavWindowingTimer += io.DeltaTime;
g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // 1.0f
if ((keyboard_next_window || keyboard_prev_window) && !just_started_windowing_from_null_focus)
NavUpdateWindowingTarget(keyboard_next_window ? -1 : +1);
@ -13838,10 +13862,10 @@ static void ImGui::NavUpdateWindowing()
windowing_toggle_layer_start = true;
g.NavWindowingToggleLayer = true;
g.NavWindowingToggleKey = windowing_toggle_key;
g.NavInputSource = ImGuiInputSource_Keyboard;
g.NavWindowingInputSource = g.NavInputSource = ImGuiInputSource_Keyboard;
break;
}
if (g.NavWindowingToggleLayer && g.NavInputSource == ImGuiInputSource_Keyboard)
if (g.NavWindowingToggleLayer && g.NavWindowingInputSource == ImGuiInputSource_Keyboard)
{
// We cancel toggling nav layer when any text has been typed (generally while holding Alt). (See #370)
// We cancel toggling nav layer when other modifiers are pressed. (See #4439)
@ -14304,7 +14328,7 @@ void ImGui::RenderDragDropTargetRect(const ImRect& bb, const ImRect& item_clip_r
bool push_clip_rect = !window->ClipRect.Contains(bb_display);
if (push_clip_rect)
window->DrawList->PushClipRectFullScreen();
window->DrawList->AddRect(bb_display.Min, bb_display.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, 0, 2.0f);
window->DrawList->AddRect(bb_display.Min, bb_display.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, 0, 2.0f); // FIXME-DPI
if (push_clip_rect)
window->DrawList->PopClipRect();
}
@ -16554,9 +16578,9 @@ void ImGui::DebugNodeWindowsListByBeginStackParent(ImGuiWindow** windows, int wi
ImFormatString(buf, IM_ARRAYSIZE(buf), "[%04d] Window", window->BeginOrderWithinContext);
//BulletText("[%04d] Window '%s'", window->BeginOrderWithinContext, window->Name);
DebugNodeWindow(window, buf);
Indent();
TreePush(buf);
DebugNodeWindowsListByBeginStackParent(windows + i + 1, windows_size - i - 1, window);
Unindent();
TreePop();
}
}

31
imgui.h
View file

@ -1,4 +1,4 @@
// dear imgui, v1.91.9b
// dear imgui, v1.92.0 WIP
// (headers)
// Help:
@ -28,8 +28,8 @@
// Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.91.9b"
#define IMGUI_VERSION_NUM 19191
#define IMGUI_VERSION "1.92.0 WIP"
#define IMGUI_VERSION_NUM 19193
#define IMGUI_HAS_TABLE
/*
@ -696,7 +696,7 @@ namespace ImGui
// - This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label.
// - If you don't need a label you can probably simply use BeginChild() with the ImGuiChildFlags_FrameStyle flag for the same result.
// - You can submit contents and manage your selection state however you want it, by creating e.g. Selectable() or any other items.
// - The simplified/old ListBox() api are helpers over BeginListBox()/EndListBox() which are kept available for convenience purpose. This is analoguous to how Combos are created.
// - The simplified/old ListBox() api are helpers over BeginListBox()/EndListBox() which are kept available for convenience purpose. This is analogous to how Combos are created.
// - Choose frame width: size.x > 0.0f: custom / size.x < 0.0f or -FLT_MIN: right-align / size.x = 0.0f (default): use current ItemWidth
// - Choose frame height: size.y > 0.0f: custom / size.y < 0.0f or -FLT_MIN: bottom-align / size.y = 0.0f (default): arbitrary default height which can fit ~7 items
IMGUI_API bool BeginListBox(const char* label, const ImVec2& size = ImVec2(0, 0)); // open a framed scrolling region
@ -1022,7 +1022,7 @@ namespace ImGui
IMGUI_API void ResetMouseDragDelta(ImGuiMouseButton button = 0); //
IMGUI_API ImGuiMouseCursor GetMouseCursor(); // get desired mouse cursor shape. Important: reset in ImGui::NewFrame(), this is updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you
IMGUI_API void SetMouseCursor(ImGuiMouseCursor cursor_type); // set desired mouse cursor shape
IMGUI_API void SetNextFrameWantCaptureMouse(bool want_capture_mouse); // Override io.WantCaptureMouse flag next frame (said flag is left for your application to handle, typical when true it instucts your app to ignore inputs). This is equivalent to setting "io.WantCaptureMouse = want_capture_mouse;" after the next NewFrame() call.
IMGUI_API void SetNextFrameWantCaptureMouse(bool want_capture_mouse); // Override io.WantCaptureMouse flag next frame (said flag is left for your application to handle, typical when true it instructs your app to ignore inputs). This is equivalent to setting "io.WantCaptureMouse = want_capture_mouse;" after the next NewFrame() call.
// Clipboard Utilities
// - Also see the LogToClipboard() function to capture GUI into clipboard, or easily output text data to the clipboard.
@ -1214,6 +1214,12 @@ enum ImGuiTreeNodeFlags_
ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 17, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop)
ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog,
// [EXPERIMENTAL] Draw lines connecting TreeNode hierarchy. Discuss in GitHub issue #2920.
// Default value is pulled from style.TreeLinesFlags. May be overridden in TreeNode calls.
ImGuiTreeNodeFlags_DrawLinesNone = 1 << 18, // No lines drawn
ImGuiTreeNodeFlags_DrawLinesFull = 1 << 19, // Horizontal lines to child nodes. Vertical line drawn down to TreePop() position: cover full contents.
ImGuiTreeNodeFlags_DrawLinesToNodes = 1 << 20, // Horizontal lines to child nodes. Vertical line drawn down to bottom-most child node. A little bit slower.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiTreeNodeFlags_AllowItemOverlap = ImGuiTreeNodeFlags_AllowOverlap, // Renamed in 1.89.7
ImGuiTreeNodeFlags_SpanTextWidth = ImGuiTreeNodeFlags_SpanLabelWidth,// Renamed in 1.90.7
@ -1648,6 +1654,7 @@ enum ImGuiCol_
ImGuiCol_ResizeGrip, // Resize grip in lower-right and lower-left corners of windows.
ImGuiCol_ResizeGripHovered,
ImGuiCol_ResizeGripActive,
ImGuiCol_InputTextCursor, // InputText cursor/caret
ImGuiCol_TabHovered, // Tab background, when hovered
ImGuiCol_Tab, // Tab background, when tab-bar is focused & tab is unselected
ImGuiCol_TabSelected, // Tab background, when tab-bar is focused & tab is selected
@ -1665,7 +1672,8 @@ enum ImGuiCol_
ImGuiCol_TableRowBg, // Table row background (even rows)
ImGuiCol_TableRowBgAlt, // Table row background (odd rows)
ImGuiCol_TextLink, // Hyperlink color
ImGuiCol_TextSelectedBg,
ImGuiCol_TextSelectedBg, // Selected text inside an InputText
ImGuiCol_TreeLines, // Tree node hierarchy outlines when using ImGuiTreeNodeFlags_DrawLines
ImGuiCol_DragDropTarget, // Rectangle highlighting a drop target
ImGuiCol_NavCursor, // Color of keyboard/gamepad navigation cursor/rectangle, when visible
ImGuiCol_NavWindowingHighlight, // Highlight window when using CTRL+TAB
@ -1721,6 +1729,7 @@ enum ImGuiStyleVar_
ImGuiStyleVar_TabBarOverlineSize, // float TabBarOverlineSize
ImGuiStyleVar_TableAngledHeadersAngle, // float TableAngledHeadersAngle
ImGuiStyleVar_TableAngledHeadersTextAlign,// ImVec2 TableAngledHeadersTextAlign
ImGuiStyleVar_TreeLinesSize, // float TreeLinesSize
ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign
ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign
ImGuiStyleVar_SeparatorTextBorderSize, // float SeparatorTextBorderSize
@ -2180,6 +2189,8 @@ struct ImGuiStyle
float TabBarOverlineSize; // Thickness of tab-bar overline, which highlights the selected tab-bar.
float TableAngledHeadersAngle; // Angle of angled headers (supported values range from -50.0f degrees to +50.0f degrees).
ImVec2 TableAngledHeadersTextAlign;// Alignment of angled headers within the cell
ImGuiTreeNodeFlags TreeLinesFlags; // Default way to draw lines connecting TreeNode hierarchy. ImGuiTreeNodeFlags_DrawLinesNone or ImGuiTreeNodeFlags_DrawLinesFull or ImGuiTreeNodeFlags_DrawLinesToNodes.
float TreeLinesSize; // Thickness of outlines when using ImGuiTreeNodeFlags_DrawLines.
ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered).
ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
@ -2730,6 +2741,7 @@ struct ImGuiListClipper
#ifdef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED
IM_MSVC_RUNTIME_CHECKS_OFF
// ImVec2 operators
static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); }
static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); }
static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); }
@ -2745,9 +2757,14 @@ static inline ImVec2& operator*=(ImVec2& lhs, const ImVec2& rhs) { lhs.x
static inline ImVec2& operator/=(ImVec2& lhs, const ImVec2& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; return lhs; }
static inline bool operator==(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; }
static inline bool operator!=(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y; }
// ImVec4 operators
static inline ImVec4 operator*(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); }
static inline ImVec4 operator/(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); }
static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); }
static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); }
static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); }
static inline ImVec4 operator/(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); }
static inline ImVec4 operator-(const ImVec4& lhs) { return ImVec4(-lhs.x, -lhs.y, -lhs.z, -lhs.w); }
static inline bool operator==(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w; }
static inline bool operator!=(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z || lhs.w != rhs.w; }
IM_MSVC_RUNTIME_CHECKS_RESTORE
@ -3287,7 +3304,7 @@ struct ImFontConfig
float GlyphExtraAdvanceX; // 0 // Extra spacing (in pixels) between glyphs. Please contact us if you are using this.
unsigned int FontBuilderFlags; // 0 // Settings for custom font builder. THIS IS BUILDER IMPLEMENTATION DEPENDENT. Leave as zero if unsure.
float RasterizerMultiply; // 1.0f // Linearly brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. This is a silly thing we may remove in the future.
float RasterizerDensity; // 1.0f // DPI scale for rasterization, not altering other font metrics: make it easy to swap between e.g. a 100% and a 400% fonts for a zooming display. IMPORTANT: If you increase this it is expected that you increase font scale accordingly, otherwise quality may look lowered.
float RasterizerDensity; // 1.0f // DPI scale for rasterization, not altering other font metrics: make it easy to swap between e.g. a 100% and a 400% fonts for a zooming display, or handle Retina screen. IMPORTANT: If you change this it is expected that you increase/decrease font scale roughly to the inverse of this, otherwise quality may look lowered.
ImWchar EllipsisChar; // 0 // Explicitly specify Unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used.
// [Internal]

View file

@ -1,4 +1,4 @@
// dear imgui, v1.91.9b
// dear imgui, v1.92.0 WIP
// (demo code)
// Help:
@ -2388,7 +2388,7 @@ static const char* ExampleNames[] =
struct ExampleSelectionWithDeletion : ImGuiSelectionBasicStorage
{
// Find which item should be Focused after deletion.
// Call _before_ item submission. Retunr an index in the before-deletion item list, your item loop should call SetKeyboardFocusHere() on it.
// Call _before_ item submission. Return an index in the before-deletion item list, your item loop should call SetKeyboardFocusHere() on it.
// The subsequent ApplyDeletionPostLoop() code will use it to apply Selection.
// - We cannot provide this logic in core Dear ImGui because we don't have access to selection data.
// - We don't actually manipulate the ImVector<> here, only in ApplyDeletionPostLoop(), but using similar API for consistency and flexibility.
@ -3920,6 +3920,7 @@ static void DemoWindowWidgetsTreeNodes()
IMGUI_DEMO_MARKER("Widgets/Tree Nodes");
if (ImGui::TreeNode("Tree Nodes"))
{
// See see "Examples -> Property Editor" (ShowExampleAppPropertyEditor() function) for a fancier, data-driven tree.
IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Basic trees");
if (ImGui::TreeNode("Basic trees"))
{
@ -3946,6 +3947,35 @@ static void DemoWindowWidgetsTreeNodes()
ImGui::TreePop();
}
IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Hierarchy lines");
if (ImGui::TreeNode("Hierarchy lines"))
{
static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DefaultOpen;
HelpMarker("Default option for DrawLinesXXX is stored in style.TreeLinesFlags");
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_DrawLinesNone", &base_flags, ImGuiTreeNodeFlags_DrawLinesNone);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_DrawLinesFull", &base_flags, ImGuiTreeNodeFlags_DrawLinesFull);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_DrawLinesToNodes", &base_flags, ImGuiTreeNodeFlags_DrawLinesToNodes);
if (ImGui::TreeNodeEx("Parent", base_flags))
{
if (ImGui::TreeNodeEx("Child 1", base_flags))
{
ImGui::Button("Button for Child 1");
ImGui::TreePop();
}
if (ImGui::TreeNodeEx("Child 2", base_flags))
{
ImGui::Button("Button for Child 2");
ImGui::TreePop();
}
ImGui::Text("Remaining contents");
ImGui::Text("Remaining contents");
ImGui::TreePop();
}
ImGui::TreePop();
}
IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Advanced, with Selectable nodes");
if (ImGui::TreeNode("Advanced, with Selectable nodes"))
{
@ -3964,6 +3994,12 @@ static void DemoWindowWidgetsTreeNodes()
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_AllowOverlap", &base_flags, ImGuiTreeNodeFlags_AllowOverlap);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_Framed", &base_flags, ImGuiTreeNodeFlags_Framed); ImGui::SameLine(); HelpMarker("Draw frame with background (e.g. for CollapsingHeader)");
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_NavLeftJumpsBackHere", &base_flags, ImGuiTreeNodeFlags_NavLeftJumpsBackHere);
HelpMarker("Default option for DrawLinesXXX is stored in style.TreeLinesFlags");
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_DrawLinesNone", &base_flags, ImGuiTreeNodeFlags_DrawLinesNone);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_DrawLinesFull", &base_flags, ImGuiTreeNodeFlags_DrawLinesFull);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_DrawLinesToNodes", &base_flags, ImGuiTreeNodeFlags_DrawLinesToNodes);
ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position);
ImGui::Checkbox("Test tree node as drag source", &test_drag_and_drop);
ImGui::Text("Hello!");
@ -4607,10 +4643,11 @@ static void DemoWindowLayout()
ImGui::SmallButton("SmallButton()");
// Tree
// (here the node appears after a button and has odd intent, so we use ImGuiTreeNodeFlags_DrawLinesNone to disable hierarchy outline)
const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
ImGui::Button("Button##1");
ImGui::SameLine(0.0f, spacing);
if (ImGui::TreeNode("Node##1"))
if (ImGui::TreeNodeEx("Node##1", ImGuiTreeNodeFlags_DrawLinesNone))
{
// Placeholder tree data
for (int i = 0; i < 6; i++)
@ -5399,7 +5436,7 @@ struct MyItem
return (sort_spec->SortDirection == ImGuiSortDirection_Ascending) ? -1 : +1;
}
// qsort() is instable so always return a way to differenciate items.
// qsort() is instable so always return a way to differentiate items.
// Your own compare function may want to avoid fallback on implicit sort specs.
// e.g. a Name compare if it wasn't already part of the sort specs.
return (a->ID - b->ID);
@ -6592,7 +6629,7 @@ static void DemoWindowTables()
{
static ImGuiTableFlags table_flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
static ImGuiTreeNodeFlags tree_node_flags_base = ImGuiTreeNodeFlags_SpanAllColumns;
static ImGuiTreeNodeFlags tree_node_flags_base = ImGuiTreeNodeFlags_SpanAllColumns | ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_DrawLinesFull;
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &tree_node_flags_base, ImGuiTreeNodeFlags_SpanFullWidth);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanLabelWidth", &tree_node_flags_base, ImGuiTreeNodeFlags_SpanLabelWidth);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &tree_node_flags_base, ImGuiTreeNodeFlags_SpanAllColumns);
@ -7762,7 +7799,7 @@ static void DemoWindowInputs()
ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
// 2: InputText also polling for CTRL+A: it always uses _RouteFocused internally (gets priority when active)
// (Commmented because the owner-aware version of Shortcut() is still in imgui_internal.h)
// (Commented because the owner-aware version of Shortcut() is still in imgui_internal.h)
//char str[16] = "Press CTRL+A";
//ImGui::Spacing();
//ImGui::InputText("InputTextB", str, IM_ARRAYSIZE(str), ImGuiInputTextFlags_ReadOnly);
@ -7789,7 +7826,7 @@ static void DemoWindowInputs()
{
ImGui::Text("(in PopupF)");
ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
// (Commmented because the owner-aware version of Shortcut() is still in imgui_internal.h)
// (Commented because the owner-aware version of Shortcut() is still in imgui_internal.h)
//ImGui::InputText("InputTextG", str, IM_ARRAYSIZE(str), ImGuiInputTextFlags_ReadOnly);
//ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags, ImGui::GetItemID()) ? "PRESSED" : "...");
ImGui::EndPopup();
@ -8139,6 +8176,14 @@ bool ImGui::ShowStyleSelector(const char* label)
return false;
}
static const char* GetTreeLinesFlagsName(ImGuiTreeNodeFlags flags)
{
if (flags == ImGuiTreeNodeFlags_DrawLinesNone) return "DrawLinesNone";
if (flags == ImGuiTreeNodeFlags_DrawLinesFull) return "DrawLinesFull";
if (flags == ImGuiTreeNodeFlags_DrawLinesToNodes) return "DrawLinesToNodes";
return "";
}
void ImGui::ShowStyleEditor(ImGuiStyle* ref)
{
IMGUI_DEMO_MARKER("Tools/Style Editor");
@ -8233,6 +8278,15 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
style.WindowMenuButtonPosition = (ImGuiDir)(window_menu_button_position - 1);
ImGui::SeparatorText("Widgets");
if (ImGui::BeginCombo("TreeLinesFlags", GetTreeLinesFlagsName(style.TreeLinesFlags)))
{
const ImGuiTreeNodeFlags options[] = { ImGuiTreeNodeFlags_DrawLinesNone, ImGuiTreeNodeFlags_DrawLinesFull, ImGuiTreeNodeFlags_DrawLinesToNodes };
for (ImGuiTreeNodeFlags option : options)
if (ImGui::Selectable(GetTreeLinesFlagsName(option), style.TreeLinesFlags == option))
style.TreeLinesFlags = option;
ImGui::EndCombo();
}
ImGui::SliderFloat("TreeLinesSize", &style.TreeLinesSize, 0.0f, 1.0f, "%.0f");
ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0");
ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f");
ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content.");
@ -9285,8 +9339,10 @@ struct ExampleAppPropertyEditor
ImGui::TableNextColumn();
ImGui::PushID(node->UID);
ImGuiTreeNodeFlags tree_flags = ImGuiTreeNodeFlags_None;
tree_flags |= ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; // Standard opening mode as we are likely to want to add selection afterwards
tree_flags |= ImGuiTreeNodeFlags_NavLeftJumpsBackHere; // Left arrow support
tree_flags |= ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;// Standard opening mode as we are likely to want to add selection afterwards
tree_flags |= ImGuiTreeNodeFlags_NavLeftJumpsBackHere; // Left arrow support
tree_flags |= ImGuiTreeNodeFlags_SpanFullWidth; // Span full width for easier mouse reach
tree_flags |= ImGuiTreeNodeFlags_DrawLinesToNodes; // Always draw hierarchy outlines
if (node == VisibleNode)
tree_flags |= ImGuiTreeNodeFlags_Selected;
if (node->Childs.Size == 0)
@ -10368,7 +10424,7 @@ struct ExampleAssetsBrowser
Selection.Clear();
}
// Logic would be written in the main code BeginChild() and outputing to local variables.
// Logic would be written in the main code BeginChild() and outputting to local variables.
// We extracted it into a function so we can call it easily from multiple places.
void UpdateLayoutSizes(float avail_width)
{

View file

@ -1,4 +1,4 @@
// dear imgui, v1.91.9b
// dear imgui, v1.92.0 WIP
// (drawing and font code)
/*
@ -217,6 +217,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst)
colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.20f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
colors[ImGuiCol_InputTextCursor] = colors[ImGuiCol_Text];
colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f);
colors[ImGuiCol_TabSelected] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
@ -235,6 +236,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst)
colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
colors[ImGuiCol_TextLink] = colors[ImGuiCol_HeaderActive];
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border];
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_NavCursor] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
@ -280,6 +282,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst)
colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.10f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.82f, 1.00f, 0.90f);
colors[ImGuiCol_InputTextCursor] = colors[ImGuiCol_Text];
colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f);
colors[ImGuiCol_TabSelected] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
@ -298,6 +301,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst)
colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.07f);
colors[ImGuiCol_TextLink] = colors[ImGuiCol_HeaderActive];
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border];
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_NavCursor] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
@ -344,6 +348,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
colors[ImGuiCol_ResizeGrip] = ImVec4(0.35f, 0.35f, 0.35f, 0.17f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
colors[ImGuiCol_InputTextCursor] = colors[ImGuiCol_Text];
colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.90f);
colors[ImGuiCol_TabSelected] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
@ -362,6 +367,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
colors[ImGuiCol_TableRowBgAlt] = ImVec4(0.30f, 0.30f, 0.30f, 0.09f);
colors[ImGuiCol_TextLink] = colors[ImGuiCol_HeaderActive];
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border];
colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
colors[ImGuiCol_NavCursor] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.70f, 0.70f, 0.70f, 0.70f);
@ -853,7 +859,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
dm_x *= half_draw_size; // dm_x, dm_y are offset to the outer edge of the AA area
dm_y *= half_draw_size;
// Add temporary vertexes for the outer edges
// Add temporary vertices for the outer edges
ImVec2* out_vtx = &temp_points[i2 * 2];
out_vtx[0].x = points[i2].x + dm_x;
out_vtx[0].y = points[i2].y + dm_y;
@ -880,7 +886,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
idx1 = idx2;
}
// Add vertexes for each point on the line
// Add vertices for each point on the line
if (use_texture)
{
// If we're using textures we only need to emit the left/right edge vertices
@ -4006,7 +4012,7 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c
}
// Allow wrapping after punctuation.
inside_word = (c != '.' && c != ',' && c != ';' && c != '!' && c != '?' && c != '\"');
inside_word = (c != '.' && c != ',' && c != ';' && c != '!' && c != '?' && c != '\"' && c != 0x3001 && c != 0x3002);
}
// We ignore blank width at the end of the line (they can be skipped)
@ -4024,7 +4030,7 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c
// Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity.
// +1 may not be a character start point in UTF-8 but it's ok because caller loops use (text >= word_wrap_eol).
if (s == text && text < text_end)
return s + 1;
return s + ImTextCountUtf8BytesFromChar(s, text_end);
return s;
}

View file

@ -1,4 +1,4 @@
// dear imgui, v1.91.9b
// dear imgui, v1.92.0 WIP
// (internal structures/api)
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
@ -994,9 +994,11 @@ enum ImGuiSelectableFlagsPrivate_
// Extend ImGuiTreeNodeFlags_
enum ImGuiTreeNodeFlagsPrivate_
{
ImGuiTreeNodeFlags_NoNavFocus = 1 << 27,// Don't claim nav focus when interacting with this item (#8551)
ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 28,// FIXME-WIP: Hard-coded for CollapsingHeader()
ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 29,// FIXME-WIP: Turn Down arrow into an Up arrow, for reversed trees (#6517)
ImGuiTreeNodeFlags_OpenOnMask_ = ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_OpenOnArrow,
ImGuiTreeNodeFlags_DrawLinesMask_ = ImGuiTreeNodeFlags_DrawLinesNone | ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DrawLinesToNodes,
};
enum ImGuiSeparatorFlags_
@ -1290,8 +1292,10 @@ struct ImGuiTreeNodeStackData
{
ImGuiID ID;
ImGuiTreeNodeFlags TreeFlags;
ImGuiItemFlags ItemFlags; // Used for nav landing
ImRect NavRect; // Used for nav landing
ImGuiItemFlags ItemFlags; // Used for nav landing
ImRect NavRect; // Used for nav landing
float DrawLinesX1;
float DrawLinesY2;
};
// sizeof() = 20
@ -2240,6 +2244,7 @@ struct ImGuiContext
bool NavJustMovedToHasSelectionData; // Copy of move result's ItemFlags & ImGuiItemFlags_HasSelectionUserData). Maybe we should just store ImGuiNavItemData.
// Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
bool ConfigNavWindowingWithGamepad; // = true. Enable CTRL+TAB by holding ImGuiKey_GamepadFaceLeft (== ImGuiKey_NavGamepadMenu). When false, the button may still be used to toggle Menu layer.
ImGuiKeyChord ConfigNavWindowingKeyNext; // = ImGuiMod_Ctrl | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiKey_Tab on OS X). For reconfiguration (see #4828)
ImGuiKeyChord ConfigNavWindowingKeyPrev; // = ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiMod_Shift | ImGuiKey_Tab on OS X)
ImGuiWindow* NavWindowingTarget; // Target window when doing CTRL+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most!
@ -2247,6 +2252,7 @@ struct ImGuiContext
ImGuiWindow* NavWindowingListWindow; // Internal window actually listing the CTRL+Tab contents
float NavWindowingTimer;
float NavWindowingHighlightAlpha;
ImGuiInputSource NavWindowingInputSource;
bool NavWindowingToggleLayer;
ImGuiKey NavWindowingToggleKey;
ImVec2 NavWindowingAccumDeltaPos;
@ -3049,7 +3055,7 @@ namespace ImGui
// NewFrame
IMGUI_API void UpdateInputEvents(bool trickle_fast_inputs);
IMGUI_API void UpdateHoveredWindowAndCaptureFlags();
IMGUI_API void UpdateHoveredWindowAndCaptureFlags(const ImVec2& mouse_pos);
IMGUI_API void FindHoveredWindowEx(const ImVec2& pos, bool find_first_and_in_any_viewport, ImGuiWindow** out_hovered_window, ImGuiWindow** out_hovered_window_under_moving_window);
IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window);
IMGUI_API void UpdateMouseMovingWindowNewFrame();
@ -3175,7 +3181,7 @@ namespace ImGui
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(ImGuiNavItemData* result);
IMGUI_API void NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiTreeNodeStackData* tree_node_data);
IMGUI_API void NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, const ImGuiTreeNodeStackData* tree_node_data);
IMGUI_API void NavMoveRequestCancel();
IMGUI_API void NavMoveRequestApplyResult();
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
@ -3461,6 +3467,7 @@ namespace ImGui
// Widgets: Tree Nodes
IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL);
IMGUI_API void TreeNodeDrawLineToChildNode(const ImVec2& target_pos);
IMGUI_API void TreePushOverrideID(ImGuiID id);
IMGUI_API bool TreeNodeGetOpen(ImGuiID storage_id);
IMGUI_API void TreeNodeSetOpen(ImGuiID storage_id, bool open);

View file

@ -1,4 +1,4 @@
// dear imgui, v1.91b
// dear imgui, v1.92.0 WIP
// (tables and columns code)
/*
@ -451,6 +451,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
// But at this point we do NOT have a correct value for .Max.y (unless a height has been explicitly passed in). It will only be updated in EndTable().
table->WorkRect = table->OuterRect = table->InnerRect = outer_rect;
table->HasScrollbarYPrev = table->HasScrollbarYCurr = false;
table->InnerWindow->DC.TreeDepth++; // This is designed to always linking ImGuiTreeNodeFlags_DrawLines linking accross a table
}
// Push a standardized ID for both child-using and not-child-using tables
@ -1510,6 +1511,7 @@ void ImGui::EndTable()
}
else
{
table->InnerWindow->DC.TreeDepth--;
ItemSize(table->OuterRect.GetSize());
ItemAdd(table->OuterRect, 0);
}

View file

@ -1,4 +1,4 @@
// dear imgui, v1.91b
// dear imgui, v1.92.0 WIP
// (widgets code)
/*
@ -494,7 +494,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args)
// And better standardize how widgets use 'GetColor32((held && hovered) ? ... : hovered ? ...)' vs 'GetColor32(held ? ... : hovered ? ...);'
// For mouse feedback we typically prefer the 'held && hovered' test, but for nav feedback not always. Outputting hovered=true on Activation may be misleading.
// - Since v1.91.2 (Sept 2024) we included io.ConfigDebugHighlightIdConflicts feature.
// One idiom which was previously valid which will now emit a warning is when using multiple overlayed ButtonBehavior()
// One idiom which was previously valid which will now emit a warning is when using multiple overlaid ButtonBehavior()
// with same ID and different MouseButton (see #8030). You can fix it by:
// (1) switching to use a single ButtonBehavior() with multiple _MouseButton flags.
// or (2) surrounding those calls with PushItemFlag(ImGuiItemFlags_AllowDuplicateId, true); ... PopItemFlag()
@ -518,7 +518,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
flags |= (item_flags & ImGuiItemFlags_ButtonRepeat) ? ImGuiButtonFlags_PressedOnClick : ImGuiButtonFlags_PressedOnDefault_;
ImGuiWindow* backup_hovered_window = g.HoveredWindow;
const bool flatten_hovered_children = (flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredWindow && g.HoveredWindow->RootWindow == window;
const bool flatten_hovered_children = (flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredWindow && g.HoveredWindow->RootWindow == window->RootWindow;
if (flatten_hovered_children)
g.HoveredWindow = window;
@ -867,11 +867,12 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)
if (hovered)
window->DrawList->AddRectFilled(bb.Min, bb.Max, bg_col);
RenderNavCursor(bb, id, ImGuiNavRenderCursorFlags_Compact);
ImU32 cross_col = GetColorU32(ImGuiCol_Text);
ImVec2 cross_center = bb.GetCenter() - ImVec2(0.5f, 0.5f);
float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, +cross_extent), cross_center + ImVec2(-cross_extent, -cross_extent), cross_col, 1.0f);
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, -cross_extent), cross_center + ImVec2(-cross_extent, +cross_extent), cross_col, 1.0f);
const ImU32 cross_col = GetColorU32(ImGuiCol_Text);
const ImVec2 cross_center = bb.GetCenter() - ImVec2(0.5f, 0.5f);
const float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
const float cross_thickness = 1.0f; // FIXME-DPI
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, +cross_extent), cross_center + ImVec2(-cross_extent, -cross_extent), cross_col, cross_thickness);
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, -cross_extent), cross_center + ImVec2(-cross_extent, +cross_extent), cross_col, cross_thickness);
return pressed;
}
@ -1478,7 +1479,7 @@ bool ImGui::TextLink(const char* label)
}
float line_y = bb.Max.y + ImFloor(g.Font->Descent * g.FontScale * 0.20f);
window->DrawList->AddLine(ImVec2(bb.Min.x, line_y), ImVec2(bb.Max.x, line_y), GetColorU32(line_colf)); // FIXME-TEXT: Underline mode.
window->DrawList->AddLine(ImVec2(bb.Min.x, line_y), ImVec2(bb.Max.x, line_y), GetColorU32(line_colf)); // FIXME-TEXT: Underline mode // FIXME-DPI
PushStyleColor(ImGuiCol_Text, GetColorU32(text_colf));
RenderText(bb.Min, label, label_end);
@ -3890,7 +3891,7 @@ bool ImGui::InputTextWithHint(const char* label, const char* hint, char* buf, si
return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data);
}
// This is only used in the path where the multiline widget is inactivate.
// This is only used in the path where the multiline widget is inactive.
static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end)
{
int line_count = 0;
@ -4647,7 +4648,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (g.ActiveId == id)
{
// Declare some inputs, the other are registered and polled via Shortcut() routing system.
// FIXME: The reason we don't use Shortcut() is we would need a routing flag to specify multiple mods, or to all mods combinaison into individual shortcuts.
// FIXME: The reason we don't use Shortcut() is we would need a routing flag to specify multiple mods, or to all mods combination into individual shortcuts.
const ImGuiKey always_owned_keys[] = { ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_Enter, ImGuiKey_KeypadEnter, ImGuiKey_Delete, ImGuiKey_Backspace, ImGuiKey_Home, ImGuiKey_End };
for (ImGuiKey key : always_owned_keys)
SetKeyOwner(key, id);
@ -5339,7 +5340,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
ImVec2 cursor_screen_pos = ImTrunc(draw_pos + cursor_offset - draw_scroll);
ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text));
draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_InputTextCursor), 1.0f); // FIXME-DPI: Cursor thickness (#7031)
// Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
if (!is_readonly)
@ -6207,7 +6208,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
if (g.Style.FrameBorderSize > 0.0f)
RenderFrameBorder(bb.Min, bb.Max, rounding);
else
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color buttons are often in need of some sort of border
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color buttons are often in need of some sort of border // FIXME-DPI
}
// Drag and Drop Source
@ -6389,6 +6390,7 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl
// - TreeNodeV()
// - TreeNodeEx()
// - TreeNodeExV()
// - TreeNodeStoreStackData() [Internal]
// - TreeNodeBehavior() [Internal]
// - TreePush()
// - TreePop()
@ -6547,17 +6549,21 @@ bool ImGui::TreeNodeUpdateNextOpen(ImGuiID storage_id, ImGuiTreeNodeFlags flags)
// Store ImGuiTreeNodeStackData for just submitted node.
// Currently only supports 32 level deep and we are fine with (1 << Depth) overflowing into a zero, easy to increase.
static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags)
static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags, float x1)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
g.TreeNodeStack.resize(g.TreeNodeStack.Size + 1);
ImGuiTreeNodeStackData* tree_node_data = &g.TreeNodeStack.back();
ImGuiTreeNodeStackData* tree_node_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
tree_node_data->ID = g.LastItemData.ID;
tree_node_data->TreeFlags = flags;
tree_node_data->ItemFlags = g.LastItemData.ItemFlags;
tree_node_data->NavRect = g.LastItemData.NavRect;
// Initially I tried to latch value for GetColorU32(ImGuiCol_TreeLines) but it's not a good trade-off for very large trees.
tree_node_data->DrawLinesX1 = (flags & (ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DrawLinesToNodes)) ? x1 : +FLT_MAX;
tree_node_data->DrawLinesY2 = -FLT_MAX;
window->DC.TreeHasStackDataDepthMask |= (1 << window->DC.TreeDepth);
}
@ -6633,18 +6639,28 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
// For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop().
// It will become tempting to enable ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default or move it to ImGuiStyle.
bool store_tree_node_stack_data = false;
if (!(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
if ((flags & ImGuiTreeNodeFlags_DrawLinesMask_) == 0)
flags |= g.Style.TreeLinesFlags;
const bool draw_tree_lines = (flags & (ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DrawLinesToNodes)) && (frame_bb.Min.y < window->ClipRect.Max.y);// && (g.Style.TreeLinesSize > 0.0f);
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
{
if ((flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && is_open && !g.NavIdIsAlive)
if ((flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !g.NavIdIsAlive)
if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
store_tree_node_stack_data = true;
if (draw_tree_lines)
store_tree_node_stack_data = true;
}
const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
if (!is_visible)
{
if (store_tree_node_stack_data && is_open)
TreeNodeStoreStackData(flags); // Call before TreePushOverrideID()
if (draw_tree_lines && (flags & ImGuiTreeNodeFlags_DrawLinesToNodes) && (window->DC.TreeHasStackDataDepthMask & (1 << window->DC.TreeDepth)))
{
ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
parent_data->DrawLinesY2 = ImMax(parent_data->DrawLinesY2, window->DC.CursorPos.y); // Don't need to aim to mid Y position as we are clipped anyway.
}
if (is_open && store_tree_node_stack_data)
TreeNodeStoreStackData(flags, text_pos.x - text_offset_x); // Call before TreePushOverrideID()
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
TreePushOverrideID(id);
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
@ -6690,6 +6706,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick;
else
button_flags |= ImGuiButtonFlags_PressedOnClickRelease;
if (flags & ImGuiTreeNodeFlags_NoNavFocus)
button_flags |= ImGuiButtonFlags_NoNavFocus;
bool selected = (flags & ImGuiTreeNodeFlags_Selected) != 0;
const bool was_selected = selected;
@ -6804,6 +6822,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
LogSetNextTextDecoration(">", NULL);
}
if (draw_tree_lines)
TreeNodeDrawLineToChildNode(ImVec2(text_pos.x - text_offset_x, text_pos.y + g.FontSize * 0.5f));
if (span_all_columns && !span_all_columns_label)
TablePopBackgroundChannel();
@ -6818,7 +6839,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
}
if (store_tree_node_stack_data && is_open)
TreeNodeStoreStackData(flags); // Call before TreePushOverrideID()
TreeNodeStoreStackData(flags, text_pos.x - text_offset_x); // Call before TreePushOverrideID()
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
TreePushOverrideID(id); // Could use TreePush(label) but this avoid computing twice
@ -6826,6 +6847,23 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
return is_open;
}
// Draw horizontal line from our parent node
// This is only called for visible child nodes so we are not too fussy anymore about performances
void ImGui::TreeNodeDrawLineToChildNode(const ImVec2& target_pos)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
if ((window->DC.TreeHasStackDataDepthMask & (1 << (window->DC.TreeDepth - 1))) == 0)
return;
ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
float x1 = parent_data->DrawLinesX1 + ImTrunc(g.FontSize * 0.5f + g.Style.FramePadding.x); // GetTreeNodeToLabelSpacing() * 0.5f
float y = ImTrunc(target_pos.y);
parent_data->DrawLinesY2 = ImMax(parent_data->DrawLinesY2, y);
if (x1 < target_pos.x)
window->DrawList->AddLine(ImVec2(x1, y), ImVec2(target_pos.x, y), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
}
void ImGui::TreePush(const char* str_id)
{
ImGuiWindow* window = GetCurrentWindow();
@ -6862,7 +6900,7 @@ void ImGui::TreePop()
if (window->DC.TreeHasStackDataDepthMask & tree_depth_mask) // Only set during request
{
ImGuiTreeNodeStackData* data = &g.TreeNodeStack.back();
const ImGuiTreeNodeStackData* data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
IM_ASSERT(data->ID == window->IDStack.back());
if (data->TreeFlags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere)
{
@ -6870,6 +6908,18 @@ void ImGui::TreePop()
if (g.NavIdIsAlive && g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
NavMoveRequestResolveWithPastTreeNode(&g.NavMoveResultLocal, data);
}
if (data->DrawLinesX1 != +FLT_MAX && window->DC.CursorPos.y >= window->ClipRect.Min.y)
{
// Draw vertical line of the hierarchy
float y1 = ImMax(data->NavRect.Max.y, window->ClipRect.Min.y);
float y2 = (data->TreeFlags & ImGuiTreeNodeFlags_DrawLinesToNodes) ? data->DrawLinesY2 : ImTrunc(window->DC.CursorPos.y - g.Style.ItemSpacing.y - g.FontSize * 0.5f);
y2 = ImMin(y2, window->ClipRect.Max.y);
if (y1 < y2)
{
float x = data->DrawLinesX1 + ImTrunc(g.FontSize * 0.5f + g.Style.FramePadding.x); // GetTreeNodeToLabelSpacing() * 0.5f
window->DrawList->AddLine(ImVec2(x, y1), ImVec2(x, y2), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
}
}
g.TreeNodeStack.pop_back();
window->DC.TreeHasStackDataDepthMask &= ~tree_depth_mask;
}
@ -7486,7 +7536,7 @@ void ImGui::EndBoxSelect(const ImRect& scope_rect, ImGuiMultiSelectFlags ms_flag
ImRect box_select_r = bs->BoxSelectRectCurr;
box_select_r.ClipWith(scope_rect);
window->DrawList->AddRectFilled(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_SeparatorHovered, 0.30f)); // FIXME-MULTISELECT: Styling
window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavCursor)); // FIXME-MULTISELECT: Styling
window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavCursor)); // FIXME-MULTISELECT FIXME-DPI: Styling
// Scroll
const bool enable_scroll = (ms_flags & ImGuiMultiSelectFlags_ScopeWindow) && (ms_flags & ImGuiMultiSelectFlags_BoxSelectNoScroll) == 0;
@ -7690,7 +7740,7 @@ ImGuiMultiSelectIO* ImGui::EndMultiSelect()
if (ms->IsFocused)
{
// We currently don't allow user code to modify RangeSrcItem by writing to BeginIO's version, but that would be an easy change here.
if (ms->IO.RangeSrcReset || (ms->RangeSrcPassedBy == false && ms->IO.RangeSrcItem != ImGuiSelectionUserData_Invalid)) // Can't read storage->RangeSrcItem here -> we want the state at begining of the scope (see tests for easy failure)
if (ms->IO.RangeSrcReset || (ms->RangeSrcPassedBy == false && ms->IO.RangeSrcItem != ImGuiSelectionUserData_Invalid)) // Can't read storage->RangeSrcItem here -> we want the state at beginning of the scope (see tests for easy failure)
{
IMGUI_DEBUG_LOG_SELECTION("[selection] EndMultiSelect: Reset RangeSrcItem.\n"); // Will set be to NavId.
storage->RangeSrcItem = ImGuiSelectionUserData_Invalid;

View file

@ -5,8 +5,8 @@
// The data is first compressed with stb_compress() to reduce source code size.
// Then stored in a C array:
// - Base85: ~5 bytes of source code for 4 bytes of input data. 5 bytes stored in binary (suggested by @mmalex).
// - As int: ~11 bytes of source code for 4 bytes of input data. 4 bytes stored in binary. Endianness dependant, need swapping on big-endian CPU.
// - As char: ~12 bytes of source code for 4 bytes of input data. 4 bytes stored in binary. Not endianness dependant.
// - As int: ~11 bytes of source code for 4 bytes of input data. 4 bytes stored in binary. Endianness dependent, need swapping on big-endian CPU.
// - As char: ~12 bytes of source code for 4 bytes of input data. 4 bytes stored in binary. Not endianness dependent.
// Load compressed TTF fonts with ImGui::GetIO().Fonts->AddFontFromMemoryCompressedTTF()
// Build with, e.g:

View file

@ -21,7 +21,7 @@ struct ImFontBuilderIO;
// - When disabled, FreeType generates blurrier glyphs, more or less matches the stb_truetype.h
// - The Default hinting mode usually looks good, but may distort glyphs in an unusual way.
// - The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer.
// You can set those flags globaly in ImFontAtlas::FontBuilderFlags
// You can set those flags globally in ImFontAtlas::FontBuilderFlags
// You can set those flags on a per font basis in ImFontConfig::FontBuilderFlags
enum ImGuiFreeTypeBuilderFlags
{