mirror of
https://github.com/ocornut/imgui.git
synced 2026-07-17 06:31:18 +00:00
Merge branch 'master' into docking
# Conflicts: # .github/workflows/build.yml # backends/imgui_impl_opengl2.cpp # backends/imgui_impl_opengl3.cpp # backends/imgui_impl_sdl2.cpp # examples/example_apple_metal4/main.mm # imgui.cpp
This commit is contained in:
20
.github/workflows/build.yml
vendored
20
.github/workflows/build.yml
vendored
@@ -509,7 +509,7 @@ jobs:
|
||||
run: g++ -c -I. -std=c++11 -DIMGUI_IMPL_VULKAN_NO_PROTOTYPES=1 backends/imgui_impl_vulkan.cpp
|
||||
|
||||
Build-MacOS:
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-26
|
||||
name: Build - MacOS
|
||||
|
||||
defaults:
|
||||
@@ -575,8 +575,8 @@ jobs:
|
||||
- name: Build macOS example_sdl2_metal
|
||||
run: make -C examples/example_sdl2_metal
|
||||
|
||||
#- name: Build macOS example_sdl3_metal4
|
||||
# run: make -C examples/example_sdl3_metal4
|
||||
- name: Build macOS example_sdl3_metal4
|
||||
run: make -C examples/example_sdl3_metal4
|
||||
|
||||
- name: Build macOS example_sdl2_opengl2
|
||||
run: make -C examples/example_sdl2_opengl2
|
||||
@@ -593,9 +593,9 @@ jobs:
|
||||
run: xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_macos
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
#- name: Build macOS example_apple_metal4
|
||||
# run: xcodebuild -project examples/example_apple_metal4/example_apple_metal4.xcodeproj -target example_apple_metal_macos
|
||||
# if: github.event_name == 'workflow_run'
|
||||
- name: Build macOS example_apple_metal4
|
||||
run: xcodebuild -project examples/example_apple_metal4/example_apple_metal4.xcodeproj -target example_apple_metal_macos
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build macOS example_apple_opengl2
|
||||
run: xcodebuild -project examples/example_apple_opengl2/example_apple_opengl2.xcodeproj -target example_osx_opengl2
|
||||
@@ -661,10 +661,10 @@ jobs:
|
||||
name: Build - Android
|
||||
|
||||
steps:
|
||||
#- name: Setup Gradle
|
||||
# uses: gradle/actions/setup-gradle@v6
|
||||
# with:
|
||||
# gradle-version: '8.14.5'
|
||||
- name: Setup Gradle 9.4.1
|
||||
uses: gradle/actions/setup-gradle@v6
|
||||
with:
|
||||
gradle-version: '9.4.1'
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
- name: Build example_android_opengl3
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
|
||||
// 2026-07-15: Inputs: clear mouse position on touch release (AMOTION_EVENT_ACTION_UP) to prevent items from staying in hovered state. (#6627, #9474)
|
||||
// 2023-04-11: Inputs: calling new io.AddMouseSourceEvent() to discriminate Mouse from Touch events.
|
||||
// 2022-09-26: Inputs: renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
|
||||
// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion.
|
||||
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).
|
||||
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
|
||||
@@ -231,6 +233,8 @@ int32_t ImGui_ImplAndroid_HandleInputEvent(const AInputEvent* input_event)
|
||||
{
|
||||
io.AddMousePosEvent(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
|
||||
io.AddMouseButtonEvent(0, event_action == AMOTION_EVENT_ACTION_DOWN);
|
||||
if (event_action == AMOTION_EVENT_ACTION_UP) // (#6627, #9474)
|
||||
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||
// 2026-07-15: OpenGL: Backup and restore GL_UNPACK_ROW_LENGTH and GL_UNPACK_ALIGNMENT in UpdateTexture() to avoid corrupting caller GL state. (#8802, #9473)
|
||||
// 2026-04-23: OpenGL: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// 2026-03-12: OpenGL: Fixed invalid assert in ImGui_ImplOpenGL3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
@@ -268,6 +269,10 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
|
||||
|
||||
void ImGui_ImplOpenGL2_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
// Backup GL_UNPACK state that we modify, restore on exit.
|
||||
GLint last_unpack_row_length = 0; GL_CALL(glGetIntegerv(GL_UNPACK_ROW_LENGTH, &last_unpack_row_length));
|
||||
GLint last_unpack_alignment = 0; GL_CALL(glGetIntegerv(GL_UNPACK_ALIGNMENT, &last_unpack_alignment));
|
||||
|
||||
if (tex->Status == ImTextureStatus_WantCreate)
|
||||
{
|
||||
// Create and upload new texture to graphics system
|
||||
@@ -324,6 +329,10 @@ void ImGui_ImplOpenGL2_UpdateTexture(ImTextureData* tex)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
}
|
||||
|
||||
// Restore GL_UNPACK state
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, last_unpack_row_length));
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, last_unpack_alignment));
|
||||
}
|
||||
|
||||
bool ImGui_ImplOpenGL2_CreateDeviceObjects()
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||
// 2026-07-15: OpenGL: Backup and restore GL_UNPACK_ROW_LENGTH and GL_UNPACK_ALIGNMENT in UpdateTexture() to avoid corrupting caller GL state. (#8802, #9473)
|
||||
// 2026-06-17: OpenGL: Expose selected render state in ImGui_ImplOpenGL3_RenderState, Allowing to dynamically select between use of glBindSampler() and glTexParameter(). You can access in 'void* platform_io.Renderer_RenderState' during rendering.
|
||||
// 2026-06-03: OpenGL: GLSL version detection assume GLSL 410 when GL context is 4.1. Fixes an issue running on macOS with Wine. (#9427, #6577)
|
||||
// 2026-04-23: OpenGL: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
@@ -672,13 +673,14 @@ static void ImGui_ImplOpenGL3_DestroyTexture(ImTextureData* tex)
|
||||
|
||||
void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
// FIXME: Consider backing up and restoring
|
||||
// Backup GL_UNPACK state that we modify, restore on exit.
|
||||
GLint last_unpack_row_length = 0; (void)last_unpack_row_length;
|
||||
GLint last_unpack_alignment = 0; (void)last_unpack_alignment;
|
||||
if (tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates)
|
||||
{
|
||||
#ifdef GL_UNPACK_ROW_LENGTH // Not on WebGL/ES
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
|
||||
#endif
|
||||
#ifdef GL_UNPACK_ALIGNMENT
|
||||
GL_CALL(glGetIntegerv(GL_UNPACK_ROW_LENGTH, &last_unpack_row_length));
|
||||
GL_CALL(glGetIntegerv(GL_UNPACK_ALIGNMENT, &last_unpack_alignment));
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
#endif
|
||||
}
|
||||
@@ -702,6 +704,9 @@ void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
#if GL_UNPACK_ROW_LENGTH // Not on WebGL/ES
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
|
||||
#endif
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->Width, tex->Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
|
||||
|
||||
// Store identifiers
|
||||
@@ -724,7 +729,6 @@ void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->Width));
|
||||
for (ImTextureRect& r : tex->Updates)
|
||||
GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, r.x, r.y, r.w, r.h, GL_RGBA, GL_UNSIGNED_BYTE, tex->GetPixelsAt(r.x, r.y)));
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
|
||||
#else
|
||||
// GL ES doesn't have GL_UNPACK_ROW_LENGTH, so we need to (A) copy to a contiguous buffer or (B) upload line by line.
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
@@ -744,6 +748,15 @@ void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantDestroy && tex->UnusedFrames > 0)
|
||||
ImGui_ImplOpenGL3_DestroyTexture(tex);
|
||||
|
||||
// Restore GL_UNPACK state
|
||||
if (tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates)
|
||||
{
|
||||
#ifdef GL_UNPACK_ROW_LENGTH
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, last_unpack_row_length));
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, last_unpack_alignment));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file.
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||
// 2026-07-15: Inputs: restore SDL_StartTextInput()/SDL_StopTextInput() in IME handler for on-screen keyboard support on Android/mobile. (#7636, #9474)
|
||||
// 2026-04-16: Made ImGui_ImplSDL2_GetContentScaleForWindow(), ImGui_ImplSDL2_GetContentScaleForDisplay() helpers return a minimum of 1.0f, as some Linux setup seems to report <1.0f value and this breaks scaling border size. (#9369)
|
||||
// 2026-03-09: [Docking] Fixed an issue dated 2025/04/09 (1.92 WIP) where a refactor+merge caused ImGuiBackendFlags_HasMouseHoveredViewport to never be set, causing foreign windows to be ignored when deciding of hovered viewport. (#9284)
|
||||
// 2026-02-13: Inputs: systems other than X11 are back to starting mouse capture on mouse down (reverts 2025-02-26 change). Only X11 requires waiting for a drag by default (not ideal, but a better default for X11 users). Added ImGui_ImplSDL2_SetMouseCaptureMode() for X11 debugger users. (#3650, #6410, #9235)
|
||||
@@ -231,6 +232,18 @@ static void ImGui_ImplSDL2_PlatformSetImeData(ImGuiContext*, ImGuiViewport* view
|
||||
r.w = 1;
|
||||
r.h = (int)data->InputLineHeight;
|
||||
SDL_SetTextInputRect(&r);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
// SDL_StartTextInput() is needed on Android (and some other platforms) to show the on-screen keyboard. (#7636, #9474, #6306)
|
||||
// It was removed in a7703fe6 due to concerns about its relation to desktop IME, but is required on mobile.
|
||||
SDL_StartTextInput();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
SDL_StopTextInput();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-07-15: Fixed default sampler state to be linear (broken 2026-04-23). (#9470, #9378)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// 2026-03-12: Fixed invalid assert in ImGui_ImplSDLRenderer3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
@@ -79,10 +80,14 @@ static ImGui_ImplSDLRenderer3_Data* ImGui_ImplSDLRenderer3_GetBackendData()
|
||||
// Functions
|
||||
static void ImGui_ImplSDLRenderer3_SetupRenderState(SDL_Renderer* renderer)
|
||||
{
|
||||
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData();
|
||||
|
||||
// Clear out any viewports and cliprect set by the user
|
||||
// FIXME: Technically speaking there are lots of other things we could backup/setup/restore during our render process.
|
||||
SDL_SetRenderViewport(renderer, nullptr);
|
||||
SDL_SetRenderClipRect(renderer, nullptr);
|
||||
|
||||
bd->CurrentScaleMode = SDL_SCALEMODE_LINEAR;
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer3_NewFrame()
|
||||
@@ -168,6 +173,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
|
||||
// Will project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
|
||||
ImVec2 clip_scale = render_scale;
|
||||
SDL_ScaleMode last_scale_mode = bd->CurrentScaleMode;
|
||||
|
||||
// Render command lists
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
@@ -205,6 +211,9 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
|
||||
const float* uv = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, uv));
|
||||
const SDL_Color* color = (const SDL_Color*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, col)); // SDL 2.0.19+
|
||||
|
||||
if (last_scale_mode != bd->CurrentScaleMode)
|
||||
SDL_FlushRenderer(renderer);
|
||||
|
||||
// Bind texture, Draw
|
||||
SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID();
|
||||
SDL_SetTextureScaleMode(tex, bd->CurrentScaleMode);
|
||||
|
||||
@@ -45,6 +45,8 @@ Breaking Changes:
|
||||
was obsoleted in 1.90.7 (May 2024). Use `ImGuiTreeNodeFlags_SpanLabelWidth`.
|
||||
- ColorEdit: obsoleted SetColorEditOptions() function added in 1.51 (June 2017) in
|
||||
of directly poking to io.ConfigColorEditFlags. More consistent and easier to discover.
|
||||
- Drag and Drop: commented out legacy name `ImGuiDragDropFlags_SourceAutoExpirePayload`
|
||||
which obsoleted in 1.90.9 (July 2024). Use `ImGuiDragDropFlags_PayloadAutoExpire`.
|
||||
|
||||
|
||||
Other Changes:
|
||||
@@ -58,9 +60,50 @@ Other Changes:
|
||||
- Fixed double-click collapse toggle not owning the mouse button. If a
|
||||
`SetNextWindowPos()` with pivot was queued in the same frame, the second
|
||||
click could trigger another item in the same window. (#9439) [@Cleroth]
|
||||
- Added `ImGuiItemFlags_LiveEditOnInputText` and `ImGuiItemFlags_LiveEditOnInputScalar`
|
||||
flags to configure the timing of applying edits of backing variables when typing
|
||||
values using a keyboard.
|
||||
(#701, #9476, #3936, #3946, #5904, #6284, #8149, #8065, #8665, #9117, #9299, #700, #1351,
|
||||
#1875, #2060, #2215, #2380, #2550, #3083, #3338, #3556, #4373, #4714, #4885, #5184,
|
||||
#5777, #6707, #6766, #8004, #8303, #8915, #9308)
|
||||
- Until now:
|
||||
- Edits where always applied immediately to backing variable, which is equivalent
|
||||
to the `ImGuiItemFlags_LiveEditXXX` flags being enabled.
|
||||
- Typing '123' in an integer field would output successively 1, 12 then 123.
|
||||
- Most uses of `IsItemDeactivatedAfterEdit()` or `ImGuiInputTextFlags_EnterReturnsTrue`
|
||||
were actually workarounds for this issue. Advanced applications would typically
|
||||
use `IsItemDeactivatedAfterEdit()` to distinguish transactions.
|
||||
Workarounds often required a backing store for scalar values, and there were
|
||||
also a few niggles related to `IsItemDeactivatedAfterEdit()` when using +/-
|
||||
buttons of an `InputInt()` widgets.
|
||||
Many of those situations can now be naturally simplified by disabling
|
||||
`ImGuiItemFlags_LiveEditOnInputScalar`, which is expected to become the default.
|
||||
- The new flags allows disabling this behavior selectively for strings fields
|
||||
such as `InputText()` vs scalar fields: `SliderInt()`, `InputFloat()`, etc.
|
||||
- When LiveEdit is disabled, edits are applied when pressing enter, tabbing out,
|
||||
clearing a field or deactivating due to a focus loss.
|
||||
- The flag may be altered programmatically:
|
||||
PushItemFlag(ImGuiItemFlags_LiveEditOnInputScalar, false); // Disable for scalars
|
||||
SliderInt(...);
|
||||
PopItemFlag();
|
||||
PushItemFlag(ImGuiItemFlags_LiveEditOnInput, true); // Enable for all
|
||||
SliderInt(...);
|
||||
PopItemFlag();
|
||||
But with upcoming new defaults it is expected you shouldn't touch them much.
|
||||
- Both flags currently defaults to true, which matches previous behavior.
|
||||
- The expectation is that for strings/text, enabling LiveEdit is a better default.
|
||||
- The expectation is that for scalars, disable LiveEdit is a better default.
|
||||
- The short-term intent is to change `ImGuiItemFlags_LiveEditOnInputScalar` to
|
||||
default to being disabled, as soon as we get more feedback from users (SOON).
|
||||
- We intentionally are not adding `io.ConfigLiveEditXXX` fields to dictate the
|
||||
default value of each `ImGuiItemFlags_LiveEditXXX`, because this is not
|
||||
expected to be a user preference but a programmer/widget preferences.
|
||||
Also, we strive to make the toolkit consistent.
|
||||
- InputText:
|
||||
- Added `style.InputTextCursorSize` to configure cursor/caret thickness. (#7031, #9409)
|
||||
This is automatically scaled by `style.ScaleAllSizes()`.
|
||||
- Reworked `io.ConfigInputTextEnterKeepActive` mode so that pressing
|
||||
Ctrl+Enter or Shift+Enter still allows to deactivate. (#9239)
|
||||
- Tables:
|
||||
- Redesigned/rewrote code to reconcile columns and settings on topology changes. (#9108)
|
||||
- When a column label is passed to TableSetupColumn(), the underlying identifier
|
||||
@@ -146,14 +189,28 @@ Other Changes:
|
||||
- Misc:
|
||||
- Added IM_DEBUG_BREAK() handler for GCC+AArch64/ARM64. [@tom-seddon]
|
||||
- Backends:
|
||||
- Android:
|
||||
- Clear mouse position on touch release (AMOTION_EVENT_ACTION_UP) to prevent
|
||||
items from staying in hovered state. (#6627, #9474) [@Turtle-PB]
|
||||
- Metal4:
|
||||
- Added new Metal 4 backend (forked from Metal 3 backend). (#9458, #9451) [@AmelieHeinrich]
|
||||
- Added Metal-cpp support enabled with `IMGUI_IMPL_METAL_CPP` define. (#9461) [@MERL10N]
|
||||
- OpenGL2:
|
||||
- Backup and restore GL_UNPACK_ROW_LENGTH and GL_UNPACK_ALIGNMENT when updating texture
|
||||
to avoid altering caller GL state. (#8802, #9473) [@Turtle-PB]
|
||||
- OpenGL3:
|
||||
- GLSL version detection assume GLSL 410 when GL context is 4.1.
|
||||
Fixes an issue running on macOS with Wine. [#9427, #6577) [@perminovVS]
|
||||
- Expose selected render state in ImGui_ImplOpenGL3_RenderState, allowing to
|
||||
dynamically select between use of glBindSampler() and glTexParameter(). (#9378)
|
||||
- Backup and restore GL_UNPACK_ROW_LENGTH and GL_UNPACK_ALIGNMENT when updating texture
|
||||
to avoid altering caller GL state. (#8802, #9473) [@Turtle-PB]
|
||||
- SDL2:
|
||||
- Restore SDL_StartTextInput()/SDL_StopTextInput() in IME handler for on-screen keyboard
|
||||
support on Android. (#7636, #9474) [@Turtle-PB]
|
||||
- SDLRenderer3:
|
||||
- Fixed sampler change which didn't work on all graphics backends. (#7616, #9470, #9378)
|
||||
- Fixed default sampler not being Linear. Regression in 1.92.8. (#7616, #9470, #9378) [@ShiroKSH]
|
||||
- Win32:
|
||||
- Uses `SetProcessDpiAwarenessContext()` instead of `SetThreadDpiAwarenessContext()`
|
||||
when available, fixing OpenGL DPI scaling issues as e.g. NVIDIA drivers tends
|
||||
|
||||
94
imgui.cpp
94
imgui.cpp
@@ -402,6 +402,7 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
|
||||
you may use GetMainViewport()->Pos to offset hard-coded positions, e.g. SetNextWindowPos(GetMainViewport()->Pos)
|
||||
- likewise io.MousePos and GetMousePos() will use OS coordinates.
|
||||
If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos.
|
||||
- 2026/07/08 (1.92.9) - Drag and Drop: commented out legacy name `ImGuiDragDropFlags_SourceAutoExpirePayload` which obsoleted in 1.90.9 (July 2024). Use `ImGuiDragDropFlags_PayloadAutoExpire`.
|
||||
- 2026/07/06 (1.92.9) - ColorEdit: obsoleted SetColorEditOptions() function added in 1.51 (June 2017) in favor of directly poking to io.ConfigColorEditFlags. More consistent and easier to discover.
|
||||
- 2026/06/02 (1.92.9) - TreeNode: commented out legacy name ImGuiTreeNodeFlags_SpanTextWidth which was obsoleted in 1.90.7 (May 2024). Use ImGuiTreeNodeFlags_SpanLabelWidth instead.
|
||||
- 2026/05/07 (1.92.8) - DrawList: swapped the last two arguments of AddRect(), AddPolyline(), PathStroke().
|
||||
@@ -4326,6 +4327,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
|
||||
HoveredIdIsDisabled = false;
|
||||
HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f;
|
||||
ItemUnclipByLog = false;
|
||||
AnyIdHasBeenEditedThisFrame = false;
|
||||
ActiveId = 0;
|
||||
ActiveIdIsAlive = 0;
|
||||
ActiveIdTimer = 0.0f;
|
||||
@@ -4939,6 +4941,7 @@ void ImGui::MarkItemEdited(ImGuiID id)
|
||||
// ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need to fill the data.
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
//IM_ASSERT(g.LastItemData.ID == id); // Failing cases include: "widgets_inputtext_scrolling", "widgets_inputtext_multiline_status", "widgets_selectable_input" = case of e.g TempInputText() overlayed manually with different ID (#2718)
|
||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_EditedInternal;
|
||||
if (g.LastItemData.ItemFlags & ImGuiItemFlags_NoMarkEdited)
|
||||
return;
|
||||
@@ -4947,16 +4950,15 @@ void ImGui::MarkItemEdited(ImGuiID id)
|
||||
if (g.ActiveId == id || g.ActiveId == 0)
|
||||
{
|
||||
// FIXME: Can't we fully rely on LastItemData yet?
|
||||
g.ActiveIdHasBeenEditedThisFrame = true;
|
||||
g.ActiveIdHasBeenEditedBefore = true;
|
||||
if (g.DeactivatedItemData.ID == id)
|
||||
g.DeactivatedItemData.HasBeenEditedBefore = true;
|
||||
g.AnyIdHasBeenEditedThisFrame = g.ActiveIdHasBeenEditedThisFrame = g.ActiveIdHasBeenEditedBefore = true;
|
||||
}
|
||||
if (g.DeactivatedItemData.ID == id)
|
||||
g.DeactivatedItemData.HasBeenEditedBefore = true;
|
||||
|
||||
// We accept a MarkItemEdited() on drag and drop targets (see https://github.com/ocornut/imgui/issues/1875#issuecomment-978243343)
|
||||
// We accept 'ActiveIdPreviousFrame == id' for InputText() returning an edit after it has been taken ActiveId away (#4714)
|
||||
// FIXME: This assert is getting a bit meaningless over time. It helped detect some unusual use cases but eventually it is becoming an unnecessary restriction.
|
||||
IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.ActiveIdPreviousFrame == id || g.NavJustMovedToId || (g.CurrentMultiSelect != NULL && g.BoxSelectState.IsActive));
|
||||
IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.DeactivatedItemData.ID == id || g.ActiveIdPreviousFrame == id || g.NavJustMovedToId || (g.CurrentMultiSelect != NULL && g.BoxSelectState.IsActive));
|
||||
}
|
||||
|
||||
bool ImGui::IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
|
||||
@@ -5864,6 +5866,7 @@ void ImGui::NewFrame()
|
||||
g.LastActiveIdTimer += g.IO.DeltaTime;
|
||||
g.ActiveIdPreviousFrame = g.ActiveId;
|
||||
g.ActiveIdIsAlive = 0;
|
||||
g.AnyIdHasBeenEditedThisFrame = false;
|
||||
g.ActiveIdHasBeenEditedThisFrame = false;
|
||||
g.ActiveIdIsJustActivated = false;
|
||||
if (g.TempInputId != 0 && g.ActiveId != g.TempInputId)
|
||||
@@ -5878,6 +5881,8 @@ void ImGui::NewFrame()
|
||||
if (g.DeactivatedItemData.ElapseFrame < g.FrameCount)
|
||||
g.DeactivatedItemData.ID = 0;
|
||||
g.DeactivatedItemData.IsAlive = false;
|
||||
if (g.InputTextDeactivatedState.ElapseFrame < g.FrameCount)
|
||||
g.InputTextDeactivatedState.ID = 0;
|
||||
|
||||
// Record when we have been stationary as this state is preserved while over same item.
|
||||
// FIXME: The way this is expressed means user cannot alter HoverStationaryDelay during the frame to use varying values.
|
||||
@@ -6619,6 +6624,7 @@ bool ImGui::IsItemDeactivated()
|
||||
return g.DeactivatedItemData.ID == g.LastItemData.ID && g.LastItemData.ID != 0 && g.DeactivatedItemData.ElapseFrame >= g.FrameCount;
|
||||
}
|
||||
|
||||
// Since 1.92.9: consider using NoLiveEdit flags if all you need to that values are not written bo backing variable while typing.
|
||||
bool ImGui::IsItemDeactivatedAfterEdit()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@@ -6706,7 +6712,7 @@ bool ImGui::IsItemEdited()
|
||||
void ImGui::SetNextItemAllowOverlap()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
g.NextItemData.ItemFlags |= ImGuiItemFlags_AllowOverlap;
|
||||
g.NextItemData.ItemFlagsSet |= ImGuiItemFlags_AllowOverlap;
|
||||
}
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
@@ -6985,21 +6991,43 @@ ImGuiWindow* ImGui::FindWindowByName(const char* name)
|
||||
|
||||
static void ApplyWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings)
|
||||
{
|
||||
const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||
window->ViewportPos = main_viewport->Pos;
|
||||
if (settings->ViewportId)
|
||||
if (settings != NULL)
|
||||
{
|
||||
window->ViewportId = settings->ViewportId;
|
||||
window->ViewportPos = ImVec2(settings->ViewportPos.x, settings->ViewportPos.y);
|
||||
const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||
window->ViewportPos = main_viewport->Pos;
|
||||
if (settings->ViewportId)
|
||||
{
|
||||
window->ViewportId = settings->ViewportId;
|
||||
window->ViewportPos = ImVec2(settings->ViewportPos.x, settings->ViewportPos.y);
|
||||
}
|
||||
window->Pos = ImTrunc(ImVec2(settings->Pos.x + window->ViewportPos.x, settings->Pos.y + window->ViewportPos.y));
|
||||
if (settings->Size.x > 0 && settings->Size.y > 0)
|
||||
{
|
||||
window->Size = window->SizeFull = ImTrunc(ImVec2(settings->Size.x, settings->Size.y));
|
||||
window->AutoFitFramesX = window->AutoFitFramesY = 0;
|
||||
}
|
||||
window->Collapsed = settings->Collapsed;
|
||||
window->DockId = settings->DockId;
|
||||
window->DockOrder = settings->DockOrder;
|
||||
SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false);
|
||||
}
|
||||
|
||||
window->DC.CursorStartPos = window->DC.CursorMaxPos = window->DC.IdealMaxPos = window->Pos; // So first call to CalcWindowContentSizes() doesn't return crazy values
|
||||
if ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
|
||||
{
|
||||
window->AutoFitFramesX = window->AutoFitFramesY = 2;
|
||||
window->AutoFitOnlyGrows = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
window->AutoFitFramesX = (window->Size.x <= 0.0f) ? 2 : 0;
|
||||
window->AutoFitFramesY = (window->Size.y <= 0.0f) ? 2 : 0;
|
||||
window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0);
|
||||
}
|
||||
window->Pos = ImTrunc(ImVec2(settings->Pos.x + window->ViewportPos.x, settings->Pos.y + window->ViewportPos.y));
|
||||
if (settings->Size.x > 0 && settings->Size.y > 0)
|
||||
window->Size = window->SizeFull = ImTrunc(ImVec2(settings->Size.x, settings->Size.y));
|
||||
window->Collapsed = settings->Collapsed;
|
||||
window->DockId = settings->DockId;
|
||||
window->DockOrder = settings->DockOrder;
|
||||
}
|
||||
|
||||
// Note that 'settings' may be NULL.
|
||||
// Sets _Once, _Appearing, _FirstUseEver. _FirstUseEver will be cleared again if there are settings.
|
||||
static void InitOrLoadWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings)
|
||||
{
|
||||
// Initial window state with e.g. default/arbitrary window position
|
||||
@@ -7010,28 +7038,9 @@ static void InitOrLoadWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* s
|
||||
window->Size = window->SizeFull = ImVec2(0, 0);
|
||||
window->ViewportPos = main_viewport->Pos;
|
||||
window->SetWindowPosAllowFlags = window->SetWindowSizeAllowFlags = window->SetWindowCollapsedAllowFlags = window->SetWindowDockAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;
|
||||
|
||||
ApplyWindowSettings(window, settings);
|
||||
if (settings != NULL)
|
||||
{
|
||||
settings->LastUsedDate = g.SessionDate;
|
||||
SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false);
|
||||
ApplyWindowSettings(window, settings);
|
||||
}
|
||||
window->DC.CursorStartPos = window->DC.CursorMaxPos = window->DC.IdealMaxPos = window->Pos; // So first call to CalcWindowContentSizes() doesn't return crazy values
|
||||
|
||||
if ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
|
||||
{
|
||||
window->AutoFitFramesX = window->AutoFitFramesY = 2;
|
||||
window->AutoFitOnlyGrows = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (window->Size.x <= 0.0f)
|
||||
window->AutoFitFramesX = 2;
|
||||
if (window->Size.y <= 0.0f)
|
||||
window->AutoFitFramesY = 2;
|
||||
window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0);
|
||||
}
|
||||
}
|
||||
|
||||
static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags)
|
||||
@@ -12116,7 +12125,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
|
||||
g.LastItemData.ID = id;
|
||||
g.LastItemData.Rect = bb;
|
||||
g.LastItemData.NavRect = nav_bb_arg ? *nav_bb_arg : bb;
|
||||
g.LastItemData.ItemFlags = g.CurrentItemFlags | g.NextItemData.ItemFlags | extra_flags;
|
||||
g.LastItemData.ItemFlags = g.CurrentItemFlags | g.NextItemData.ItemFlagsSet | extra_flags;
|
||||
g.LastItemData.StatusFlags = ImGuiItemStatusFlags_None;
|
||||
// Note: we don't copy 'g.NextItemData.SelectionUserData' to an hypothetical g.LastItemData.SelectionUserData: since the former is not cleared.
|
||||
|
||||
@@ -12150,7 +12159,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
|
||||
|
||||
// Lightweight clear of SetNextItemXXX data.
|
||||
g.NextItemData.HasFlags = ImGuiNextItemDataFlags_None;
|
||||
g.NextItemData.ItemFlags = ImGuiItemFlags_None;
|
||||
g.NextItemData.ItemFlagsSet = ImGuiItemFlags_None;
|
||||
|
||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
|
||||
if (id != 0)
|
||||
@@ -12560,7 +12569,7 @@ void ImGui::BeginGroup()
|
||||
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
|
||||
group_data.BackupHoveredIdIsAlive = g.HoveredId != 0;
|
||||
group_data.BackupIsSameLine = window->DC.IsSameLine;
|
||||
group_data.BackupActiveIdHasBeenEditedThisFrame = g.ActiveIdHasBeenEditedThisFrame;
|
||||
group_data.BackupAnyIdHasBeenEditedThisFrame = g.AnyIdHasBeenEditedThisFrame;
|
||||
group_data.BackupDeactivatedIdIsAlive = g.DeactivatedItemData.IsAlive;
|
||||
group_data.EmitItem = true;
|
||||
|
||||
@@ -12625,7 +12634,7 @@ void ImGui::EndGroup()
|
||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
|
||||
|
||||
// Forward Edited flag
|
||||
if (g.ActiveIdHasBeenEditedThisFrame && !group_data.BackupActiveIdHasBeenEditedThisFrame)
|
||||
if (g.AnyIdHasBeenEditedThisFrame && !group_data.BackupAnyIdHasBeenEditedThisFrame)
|
||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
|
||||
|
||||
// Forward Deactivated flag
|
||||
@@ -16531,7 +16540,10 @@ void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size)
|
||||
// Call post-read handlers
|
||||
ImGuiSettingsCleanupArgs cleanup_args;
|
||||
if (g.IO.ConfigIniSettingsAutoDiscardMonths > 0)
|
||||
{
|
||||
cleanup_args.DiscardOlderThanMonths = g.IO.ConfigIniSettingsAutoDiscardMonths;
|
||||
CleanupIniSettings(&cleanup_args);
|
||||
}
|
||||
for (ImGuiSettingsHandler& handler : g.SettingsHandlers)
|
||||
if (handler.ApplyAllFn != NULL)
|
||||
handler.ApplyAllFn(&g, &handler);
|
||||
|
||||
30
imgui.h
30
imgui.h
@@ -30,7 +30,7 @@
|
||||
// Library Version
|
||||
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
|
||||
#define IMGUI_VERSION "1.92.9 WIP"
|
||||
#define IMGUI_VERSION_NUM 19285
|
||||
#define IMGUI_VERSION_NUM 19286
|
||||
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
|
||||
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
|
||||
#define IMGUI_HAS_VIEWPORT // In 'docking' WIP branch.
|
||||
@@ -1285,14 +1285,29 @@ enum ImGuiChildFlags_
|
||||
// (Those are shared by all submitted items)
|
||||
enum ImGuiItemFlags_
|
||||
{
|
||||
ImGuiItemFlags_None = 0, // (Default)
|
||||
ImGuiItemFlags_None = 0, // Default:
|
||||
ImGuiItemFlags_NoTabStop = 1 << 0, // false // Disable keyboard tabbing. This is a "lighter" version of ImGuiItemFlags_NoNav.
|
||||
ImGuiItemFlags_NoNav = 1 << 1, // false // Disable any form of focusing (keyboard/gamepad directional navigation and SetKeyboardFocusHere() calls).
|
||||
ImGuiItemFlags_NoNav = 1 << 1, // false // Disable any form of focusing: keyboard/gamepad directional navigation and SetKeyboardFocusHere() calls.
|
||||
ImGuiItemFlags_NoNavDefaultFocus = 1 << 2, // false // Disable item being a candidate for default focus (e.g. used by title bar items).
|
||||
ImGuiItemFlags_ButtonRepeat = 1 << 3, // false // Any button-like behavior will have repeat mode enabled (based on io.KeyRepeatDelay and io.KeyRepeatRate values). Note that you can also call IsItemActive() after any button to tell if it is being held.
|
||||
ImGuiItemFlags_AutoClosePopups = 1 << 4, // true // MenuItem()/Selectable() automatically close their parent popup window.
|
||||
ImGuiItemFlags_AllowDuplicateId = 1 << 5, // false // Allow submitting an item with the same identifier as an item already submitted this frame without triggering a warning tooltip if io.ConfigDebugHighlightIdConflicts is set.
|
||||
ImGuiItemFlags_Disabled = 1 << 6, // false // [Internal] Disable interactions. DOES NOT affect visuals. This is used by BeginDisabled()/EndDisabled() and only provided here so you can read back via GetItemFlags().
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// LiveEdit refers to applying edits to backing variables _while_ typing.
|
||||
// Widget: | Input: | w/ LiveEdit: | Output:
|
||||
// InputText() | "123" | on(default) | "1" then "12" then "123"
|
||||
// InputText() | "123" | off | "123" after validating or tabbing out or losing focus.
|
||||
// DragFloat(), SliderInt(), etc. | "123" | on(default)* | 1 then 12 then 123
|
||||
// DragFloat(), SliderInt(), etc. | "123" | off* | 123 after validation or tabbing out or losing focus.
|
||||
//---------------------------------------------------------------------------------
|
||||
// (*) The feature is currently being evaluated, and the aim is to change ImGuiItemFlags_LiveEditOnInputScalar to OFF by default.
|
||||
// The legacy behavior until July 2026 was that LiveEdit was always ON for everything.
|
||||
//---------------------------------------------------------------------------------
|
||||
ImGuiItemFlags_LiveEditOnInputText = 1 << 7, // true // InputText: apply keyboard edits to backing value while typing. Otherwise, edits are applied when validating, tabbing out or losing focus.
|
||||
ImGuiItemFlags_LiveEditOnInputScalar = 1 << 8, // true* // DragXXX, SliderXXX, InputScalar: apply keyboard edits to backing value while typing. Otherwise, edits are applied when validating, tabbing out or losing focus.
|
||||
ImGuiItemFlags_LiveEditOnInput = ImGuiItemFlags_LiveEditOnInputText | ImGuiItemFlags_LiveEditOnInputScalar,
|
||||
};
|
||||
|
||||
// Flags for ImGui::InputText()
|
||||
@@ -1309,7 +1324,7 @@ enum ImGuiInputTextFlags_
|
||||
|
||||
// Inputs
|
||||
ImGuiInputTextFlags_AllowTabInput = 1 << 5, // Pressing TAB input a '\t' character into the text field
|
||||
ImGuiInputTextFlags_EnterReturnsTrue = 1 << 6, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider using IsItemDeactivatedAfterEdit() instead!
|
||||
ImGuiInputTextFlags_EnterReturnsTrue = 1 << 6, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider disabling LiveEdit! or using IsItemDeactivatedAfterEdit() instead!
|
||||
ImGuiInputTextFlags_EscapeClearsAll = 1 << 7, // Escape key clears content if not empty, and deactivate otherwise (contrast to default behavior of Escape to revert)
|
||||
ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 8, // In multi-line mode: validate with Enter, add new line with Ctrl+Enter (default is opposite: validate with Ctrl+Enter, add line with Enter). Note that Shift+Enter always enter a new line either way.
|
||||
|
||||
@@ -1322,6 +1337,7 @@ enum ImGuiInputTextFlags_
|
||||
ImGuiInputTextFlags_DisplayEmptyRefVal = 1 << 14, // InputFloat(), InputInt(), InputScalar() etc. only: when value is zero, do not display it. Generally used with ImGuiInputTextFlags_ParseEmptyRefVal.
|
||||
ImGuiInputTextFlags_NoHorizontalScroll = 1 << 15, // Disable following the cursor horizontally
|
||||
ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID().
|
||||
//ImGuiInputTextFlags_NoLiveEdit = 1 << 25, // Disable applying output to backing variable while typing. Same as setting ImGuiItemFlags_LiveEditOnInput to false.
|
||||
|
||||
// Elide display / Alignment
|
||||
ImGuiInputTextFlags_ElideLeft = 1 << 17, // When text doesn't fit, elide left side to ensure right side stays visible. Useful for path/filenames. Single-line only!
|
||||
@@ -1571,7 +1587,7 @@ enum ImGuiDragDropFlags_
|
||||
ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect, // For peeking ahead and inspecting the payload before delivery.
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
ImGuiDragDropFlags_SourceAutoExpirePayload = ImGuiDragDropFlags_PayloadAutoExpire, // Renamed in 1.90.9
|
||||
//ImGuiDragDropFlags_SourceAutoExpirePayload = ImGuiDragDropFlags_PayloadAutoExpire, // Renamed in 1.90.9
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -2039,6 +2055,8 @@ enum ImGuiSliderFlags_
|
||||
ImGuiSliderFlags_NoSpeedTweaks = 1 << 11, // Disable keyboard modifiers altering tweak speed. Useful if you want to alter tweak speed yourself based on your own logic.
|
||||
ImGuiSliderFlags_ColorMarkers = 1 << 12, // DragScalarN(), SliderScalarN(): Draw R/G/B/A color markers on each component.
|
||||
ImGuiSliderFlags_AlwaysClamp = ImGuiSliderFlags_ClampOnInput | ImGuiSliderFlags_ClampZeroRange,
|
||||
//ImGuiSliderFlags_LiveEditOnInput = 1 << 13, // Shortcut to enable LiveEdit for this field.
|
||||
//ImGuiSliderFlags_NoLiveEditOnInput= 1 << 14, // Shortcut to disable LiveEdit for this field.
|
||||
ImGuiSliderFlags_InvalidMask_ = 0x7000000F, // [Internal] We treat using those bits as being potentially a 'float power' argument from legacy API (obsoleted 2020-08) that has got miscast to this enum, and will trigger an assert if needed.
|
||||
};
|
||||
|
||||
@@ -2550,7 +2568,7 @@ struct ImGuiIO
|
||||
bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
|
||||
bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
|
||||
bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting).
|
||||
bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will reactivate item and select all text (single-line only).
|
||||
bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will reactivate item and select all text (single-line only). Ctrl+Enter or Shift+Enter will deactivate normally.
|
||||
ImGuiColorEditFlags ConfigColorEditFlags; // = <defaults> // Current settings for ColorEdit/ColorPicker widgets. Must have one bit of ImGuiColorEditFlags_DisplayMask_, one bit of ImGuiColorEditFlags_DataTypeMask_, one bit of ImGuiColorEditFlags_PickerMask_, one bit of ImGuiColorEditFlags_InputMask_. Defaults to ImGuiColorEditFlags_DefaultOptions_. May be further edited by users, unless you also set ImGuiColorEditFlags_NoOptions.
|
||||
bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
|
||||
bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
|
||||
|
||||
@@ -86,6 +86,7 @@ Index of this file:
|
||||
// [SECTION] DemoWindowWidgetsFonts()
|
||||
// [SECTION] DemoWindowWidgetsImages()
|
||||
// [SECTION] DemoWindowWidgetsListBoxes()
|
||||
// [SECTION] DemoWindowWidgetsLiveEdit()
|
||||
// [SECTION] DemoWindowWidgetsMultiComponents()
|
||||
// [SECTION] DemoWindowWidgetsPlotting()
|
||||
// [SECTION] DemoWindowWidgetsProgressBars()
|
||||
@@ -344,6 +345,8 @@ struct ImGuiDemoWindowData
|
||||
|
||||
// Other data
|
||||
bool DisableSections = false;
|
||||
bool LiveEditOverride = false;
|
||||
ImGuiItemFlags LiveEditFlags = ImGuiItemFlags_LiveEditOnInputText;
|
||||
ExampleTreeNode* DemoTree = NULL;
|
||||
|
||||
~ImGuiDemoWindowData() { if (DemoTree) ExampleTree_DestroyNode(DemoTree); }
|
||||
@@ -2080,6 +2083,44 @@ static void DemoWindowWidgetsListBoxes()
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] DemoWindowWidgetsLiveEdit()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void DemoWindowWidgetsLiveEdit(ImGuiDemoWindowData* demo_data)
|
||||
{
|
||||
if (ImGui::TreeNode("Live Edit Flags"))
|
||||
{
|
||||
IMGUI_DEMO_MARKER("Widgets/Live Edit Flgs");
|
||||
|
||||
ImGui::TextWrapped("Select whether to apply keyboard edits to backing variables _while_ typing.");
|
||||
|
||||
ImGui::Checkbox("Override Live Edit Flags in Demo Window", &demo_data->LiveEditOverride);
|
||||
if (!demo_data->LiveEditOverride)
|
||||
demo_data->LiveEditFlags = ImGui::GetItemFlags();
|
||||
|
||||
ImGui::BeginDisabled(demo_data->LiveEditOverride == false);
|
||||
ImGui::Indent();
|
||||
ImGui::CheckboxFlags("ImGuiItemFlags_LiveEditOnInputText", &demo_data->LiveEditFlags, ImGuiItemFlags_LiveEditOnInputText);
|
||||
ImGui::CheckboxFlags("ImGuiItemFlags_LiveEditOnInputScalar", &demo_data->LiveEditFlags, ImGuiItemFlags_LiveEditOnInputScalar);
|
||||
ImGui::Unindent();
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::Text("Try typing '123' and seeing effect on backing value:");
|
||||
static char str[32] = "";
|
||||
ImGui::InputText("str", str, IM_COUNTOF(str));
|
||||
ImGui::Text("Backing value: \"%s\"", str);
|
||||
static int i = 0;
|
||||
ImGui::InputInt("int", &i, 0, 0);
|
||||
ImGui::Text("Backing value: %d", i);
|
||||
static float f = 0.0f;
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 100.0f);
|
||||
ImGui::Text("Backing value: %f", f);
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] DemoWindowWidgetsMultiComponents()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -2260,10 +2301,28 @@ static void DemoWindowWidgetsQueryingStatuses()
|
||||
};
|
||||
static int item_type = 4;
|
||||
static bool item_disabled = false;
|
||||
static bool liveedit_flags_override = false;
|
||||
static ImGuiItemFlags liveedit_flags = 0;
|
||||
ImGui::Combo("Item Type", &item_type, item_names, IM_COUNTOF(item_names), IM_COUNTOF(item_names));
|
||||
ImGui::SameLine();
|
||||
HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions. Note that the bool return value of most ImGui function is generally equivalent to calling ImGui::IsItemHovered().");
|
||||
ImGui::Checkbox("Item Disabled", &item_disabled);
|
||||
ImGui::Checkbox("Override LiveEdit:", &liveedit_flags_override);
|
||||
ImGui::SameLine();
|
||||
if (!liveedit_flags_override)
|
||||
liveedit_flags = ImGui::GetItemFlags();
|
||||
ImGui::BeginDisabled(liveedit_flags_override == false);
|
||||
ImGui::CheckboxFlags("_LiveEditOnInput", &liveedit_flags, ImGuiItemFlags_LiveEditOnInput);
|
||||
ImGui::SameLine();
|
||||
ImGui::CheckboxFlags("_LiveEditOnInputText", &liveedit_flags, ImGuiItemFlags_LiveEditOnInputText);
|
||||
ImGui::SameLine();
|
||||
ImGui::CheckboxFlags("_LiveEditOnInputScalar", &liveedit_flags, ImGuiItemFlags_LiveEditOnInputScalar);
|
||||
ImGui::EndDisabled();
|
||||
if (liveedit_flags_override)
|
||||
{
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_LiveEditOnInputText, (liveedit_flags & ImGuiItemFlags_LiveEditOnInputText) != 0);
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_LiveEditOnInputScalar, (liveedit_flags & ImGuiItemFlags_LiveEditOnInputScalar) != 0);
|
||||
}
|
||||
|
||||
// Submit selected items so we can query their status in the code following it.
|
||||
bool ret = false;
|
||||
@@ -2350,6 +2409,11 @@ static void DemoWindowWidgetsQueryingStatuses()
|
||||
"IsItemHovered(_Tooltip) = %d",
|
||||
hovered_delay_none, hovered_delay_stationary, hovered_delay_short, hovered_delay_normal, hovered_delay_tooltip);
|
||||
|
||||
if (liveedit_flags_override)
|
||||
{
|
||||
ImGui::PopItemFlag();
|
||||
ImGui::PopItemFlag();
|
||||
}
|
||||
if (item_disabled)
|
||||
ImGui::EndDisabled();
|
||||
|
||||
@@ -4499,8 +4563,14 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data)
|
||||
// IMGUI_DEMO_MARKER("Widgets");
|
||||
|
||||
const bool disable_all = demo_data->DisableSections; // The Checkbox for that is inside the "Disabled" section at the bottom
|
||||
const bool override_liveedit = demo_data->LiveEditOverride;
|
||||
if (disable_all)
|
||||
ImGui::BeginDisabled();
|
||||
if (override_liveedit)
|
||||
{
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_LiveEditOnInputText, (demo_data->LiveEditFlags & ImGuiItemFlags_LiveEditOnInputText) != 0);
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_LiveEditOnInputScalar, (demo_data->LiveEditFlags & ImGuiItemFlags_LiveEditOnInputScalar) != 0);
|
||||
}
|
||||
|
||||
DemoWindowWidgetsBasic();
|
||||
DemoWindowWidgetsBullets();
|
||||
@@ -4520,6 +4590,7 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data)
|
||||
DemoWindowWidgetsFonts();
|
||||
DemoWindowWidgetsImages();
|
||||
DemoWindowWidgetsListBoxes();
|
||||
DemoWindowWidgetsLiveEdit(demo_data);
|
||||
DemoWindowWidgetsMultiComponents();
|
||||
DemoWindowWidgetsPlotting();
|
||||
DemoWindowWidgetsProgressBars();
|
||||
@@ -4534,6 +4605,11 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data)
|
||||
DemoWindowWidgetsTreeNodes();
|
||||
DemoWindowWidgetsVerticalSliders();
|
||||
|
||||
if (override_liveedit)
|
||||
{
|
||||
ImGui::PopItemFlag();
|
||||
ImGui::PopItemFlag();
|
||||
}
|
||||
if (disable_all)
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
@@ -1017,7 +1017,7 @@ enum ImGuiItemFlagsPrivate_
|
||||
ImGuiItemFlags_HasSelectionUserData = 1 << 21, // false // Set by SetNextItemSelectionUserData()
|
||||
ImGuiItemFlags_IsMultiSelect = 1 << 22, // false // Set by SetNextItemSelectionUserData()
|
||||
|
||||
ImGuiItemFlags_Default_ = ImGuiItemFlags_AutoClosePopups, // Please don't change, use PushItemFlag() instead.
|
||||
ImGuiItemFlags_Default_ = ImGuiItemFlags_AutoClosePopups | ImGuiItemFlags_LiveEditOnInputText | ImGuiItemFlags_LiveEditOnInputScalar, // Please don't change, use PushItemFlag() instead.
|
||||
|
||||
// Obsolete
|
||||
//ImGuiItemFlags_SelectableDontClosePopup = !ImGuiItemFlags_AutoClosePopups, // Can't have a redirect as we inverted the behavior
|
||||
@@ -1220,7 +1220,7 @@ struct IMGUI_API ImGuiGroupData
|
||||
ImVec2 BackupCurrLineSize;
|
||||
float BackupCurrLineTextBaseOffset;
|
||||
ImGuiID BackupActiveIdIsAlive;
|
||||
bool BackupActiveIdHasBeenEditedThisFrame;
|
||||
bool BackupAnyIdHasBeenEditedThisFrame;
|
||||
bool BackupDeactivatedIdIsAlive;
|
||||
bool BackupHoveredIdIsAlive;
|
||||
bool BackupIsSameLine;
|
||||
@@ -1250,10 +1250,11 @@ struct IMGUI_API ImGuiMenuColumns
|
||||
struct IMGUI_API ImGuiInputTextDeactivatedState
|
||||
{
|
||||
ImGuiID ID; // widget id owning the text state (which just got deactivated)
|
||||
int ElapseFrame;
|
||||
ImVector<char> TextA; // text buffer
|
||||
|
||||
ImGuiInputTextDeactivatedState() { memset((void*)this, 0, sizeof(*this)); }
|
||||
void ClearFreeMemory() { ID = 0; TextA.clear(); }
|
||||
void ClearFreeMemory() { ID = 0; ElapseFrame = 0; TextA.clear(); }
|
||||
};
|
||||
|
||||
// Forward declare imstb_textedit.h structure + make its main configuration define accessible
|
||||
@@ -1406,7 +1407,7 @@ enum ImGuiNextItemDataFlags_
|
||||
struct ImGuiNextItemData
|
||||
{
|
||||
ImGuiNextItemDataFlags HasFlags; // Called HasFlags instead of Flags to avoid mistaking this
|
||||
ImGuiItemFlags ItemFlags; // Currently only tested/used for ImGuiItemFlags_AllowOverlap and ImGuiItemFlags_HasSelectionUserData.
|
||||
ImGuiItemFlags ItemFlagsSet; // Currently only tested/used for ImGuiItemFlags_AllowOverlap and ImGuiItemFlags_HasSelectionUserData.
|
||||
|
||||
// Members below are NOT cleared by ItemAdd() meaning they are still valid during e.g. NavProcessItem(). Always rely on HasFlags.
|
||||
ImGuiID FocusScopeId; // Set by SetNextItemSelectionUserData()
|
||||
@@ -1421,7 +1422,7 @@ struct ImGuiNextItemData
|
||||
ImU32 ColorMarker; // Set by SetNextItemColorMarker(). Not exposed yet, supported by DragScalar,SliderScalar and for ImGuiSliderFlags_ColorMarkers.
|
||||
|
||||
ImGuiNextItemData() { memset((void*)this, 0, sizeof(*this)); SelectionUserData = -1; }
|
||||
inline void ClearFlags() { HasFlags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()!
|
||||
inline void ClearFlags() { HasFlags = ImGuiNextItemDataFlags_None; ItemFlagsSet = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()!
|
||||
};
|
||||
|
||||
// Status storage for the last submitted item
|
||||
@@ -2508,6 +2509,7 @@ struct ImGuiContext
|
||||
bool HoveredIdAllowOverlap;
|
||||
bool HoveredIdIsDisabled; // At least one widget passed the rect test, but has been discarded by disabled flag or popup inhibit. May be true even if HoveredId == 0.
|
||||
bool ItemUnclipByLog; // Disable ItemAdd() clipping, essentially a memory-locality friendly copy of LogEnabled
|
||||
bool AnyIdHasBeenEditedThisFrame;
|
||||
ImGuiID ActiveId; // Active widget
|
||||
ImGuiID ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame)
|
||||
float ActiveIdTimer;
|
||||
@@ -4093,7 +4095,7 @@ namespace ImGui
|
||||
IMGUI_API void InputTextDeactivateHook(ImGuiID id);
|
||||
IMGUI_API bool TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
|
||||
IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL);
|
||||
inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return g.ActiveId == id && g.TempInputId == id; }
|
||||
inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.TempInputId == id && g.ActiveId == id) || (g.InputTextDeactivatedState.ID == id); }
|
||||
inline ImGuiInputTextState* GetInputTextState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.InputTextState.ID == id) ? &g.InputTextState : NULL; } // Get input text state if active
|
||||
IMGUI_API void SetNextItemRefVal(ImGuiDataType data_type, void* p_data);
|
||||
inline bool IsItemActiveAsInputText() { ImGuiContext& g = *GImGui; return g.ActiveId != 0 && g.ActiveId == g.LastItemData.ID && g.InputTextState.ID == g.LastItemData.ID; } // This may be useful to apply workaround that a based on distinguish whenever an item is active as a text input field.
|
||||
|
||||
@@ -4165,9 +4165,12 @@ static void TableSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandle
|
||||
|
||||
static void* TableSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name)
|
||||
{
|
||||
// FIXME: As topology changes are allowed, strictly speaking a >= IMGUI_TABLE_MAX_COLUMNS tables stored in .ini file
|
||||
// that was emitted with a higher max count could still be meaningful in some unlikely cases.
|
||||
// We might want to use another MAX defined as (1<<(sizeof(ImGuiTableColumnIdx)*8-1))-1.
|
||||
ImGuiID id = 0;
|
||||
int columns_count = 0;
|
||||
if (sscanf(name, "0x%08X,%d", &id, &columns_count) < 2)
|
||||
if (sscanf(name, "0x%08X,%d", &id, &columns_count) < 2 || columns_count <= 0 || columns_count >= IMGUI_TABLE_MAX_COLUMNS)
|
||||
return NULL;
|
||||
return ImGui::TableSettingsCreate(id, columns_count);
|
||||
}
|
||||
|
||||
@@ -1332,7 +1332,7 @@ bool ImGui::CheckboxFlagsT(const char* label, T* flags, T flags_value)
|
||||
if (!all_on && any_on)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
g.NextItemData.ItemFlags |= ImGuiItemFlags_MixedValue;
|
||||
g.NextItemData.ItemFlagsSet |= ImGuiItemFlags_MixedValue;
|
||||
pressed = Checkbox(label, &all_on);
|
||||
}
|
||||
else
|
||||
@@ -3729,8 +3729,9 @@ bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char*
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
const bool init = (g.TempInputId != id);
|
||||
if (init)
|
||||
const bool is_deactivated = (g.InputTextDeactivatedState.ID == id);
|
||||
const bool is_active = (g.TempInputId == id);
|
||||
if (!is_active && !is_deactivated)
|
||||
ClearActiveID();
|
||||
|
||||
ImVec2 backup_pos = window->DC.CursorPos;
|
||||
@@ -3738,13 +3739,13 @@ bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char*
|
||||
g.LastItemData.ItemFlags |= ImGuiItemFlags_AllowDuplicateId; // Using ImGuiInputTextFlags_MergedItem above will skip ItemAdd() so we poke here.
|
||||
bool value_changed = InputTextEx(label, NULL, buf, (int)buf_size, bb.GetSize(), flags | ImGuiInputTextFlags_TempInput | ImGuiInputTextFlags_AutoSelectAll, callback, user_data);
|
||||
KeepAliveID(id); // Not done because of ImGuiInputTextFlags_TempInput
|
||||
if (init)
|
||||
if (!is_active && !is_deactivated)
|
||||
{
|
||||
// First frame we started displaying the InputText widget, we expect it to take the active id.
|
||||
IM_ASSERT(g.ActiveId == id);
|
||||
g.TempInputId = g.ActiveId;
|
||||
}
|
||||
if (g.ActiveId != id)
|
||||
if (is_active && g.ActiveId != id)
|
||||
g.TempInputId = 0;
|
||||
window->DC.CursorPos = backup_pos;
|
||||
return value_changed;
|
||||
@@ -3769,6 +3770,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
|
||||
|
||||
ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
|
||||
g.LastItemData.ItemFlags |= ImGuiItemFlags_NoMarkEdited; // Because TempInputText() uses ImGuiInputTextFlags_MergedItem it doesn't submit a new item, so we poke LastItemData.
|
||||
g.LastItemData.ItemFlags = (g.LastItemData.ItemFlags & ImGuiItemFlags_LiveEditOnInputScalar) ? (g.LastItemData.ItemFlags | ImGuiItemFlags_LiveEditOnInputText) : (g.LastItemData.ItemFlags & ~ImGuiItemFlags_LiveEditOnInputText);
|
||||
if (!TempInputText(bb, id, label, data_buf, IM_COUNTOF(data_buf), flags))
|
||||
return false;
|
||||
|
||||
@@ -3826,7 +3828,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
|
||||
|
||||
// Disable the MarkItemEdited() call in InputText but keep ImGuiItemStatusFlags_Edited.
|
||||
// We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
|
||||
g.NextItemData.ItemFlags |= ImGuiItemFlags_NoMarkEdited;
|
||||
g.NextItemData.ItemFlagsSet |= ImGuiItemFlags_NoMarkEdited;
|
||||
flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
|
||||
|
||||
const bool has_step_buttons = (p_step != NULL);
|
||||
@@ -3848,8 +3850,23 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
|
||||
}
|
||||
|
||||
// Apply
|
||||
bool input_edited = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_EditedInternal) != 0; // We would be using 'ret' if ImGuiInputTextFlags_EnterReturnsTrue was not involved.
|
||||
bool value_changed = input_edited ? DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL) : false;
|
||||
bool value_changed = false;
|
||||
if (g.LastItemData.ItemFlags & ImGuiItemFlags_LiveEditOnInputScalar)
|
||||
{
|
||||
bool input_edited = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_EditedInternal) != 0; // We would be using 'ret' if ImGuiInputTextFlags_EnterReturnsTrue was not involved.
|
||||
if (input_edited)
|
||||
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
//g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_Edited;
|
||||
if (g.DeactivatedItemData.ID == g.LastItemData.ID)
|
||||
{
|
||||
//g.DeactivatedItemData.HasBeenEditedBefore = false; // Will be set below by MarkItemEdited()
|
||||
//if (IsItemDeactivated()) // Should be unnecessary
|
||||
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// Step buttons
|
||||
if (has_step_buttons)
|
||||
@@ -4591,10 +4608,13 @@ void ImGui::InputTextDeactivateHook(ImGuiID id)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiInputTextState* state = &g.InputTextState;
|
||||
if (id == 0 || state->ID != id)
|
||||
if (id == 0 || state->ID != id || g.ActiveId != id)
|
||||
return;
|
||||
if (!state->EditedBefore)
|
||||
return;
|
||||
//IMGUI_DEBUG_LOG_ACTIVEID("InputTextDeactivateHook() id = 0x%08X\n", id);
|
||||
g.InputTextDeactivatedState.ID = state->ID;
|
||||
g.InputTextDeactivatedState.ElapseFrame = g.FrameCount + 1;
|
||||
if (state->Flags & ImGuiInputTextFlags_ReadOnly)
|
||||
{
|
||||
g.InputTextDeactivatedState.TextA.resize(0); // In theory this data won't be used, but clear to be neat.
|
||||
@@ -4824,7 +4844,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
const bool user_clicked = hovered && io.MouseClicked[0];
|
||||
const bool input_requested_by_nav = (g.ActiveId != id) && (g.NavActivateId == id);
|
||||
const bool input_requested_by_reactivate = (g.InputTextReactivateId == id); // for io.ConfigInputTextEnterKeepActive
|
||||
const bool input_requested_by_user = (user_clicked) || (g.ActiveId == 0 && (flags & ImGuiInputTextFlags_TempInput));
|
||||
const bool input_requested_by_user = (user_clicked) || (g.ActiveId == 0 && (flags & ImGuiInputTextFlags_TempInput) && g.InputTextDeactivatedState.ID != id);
|
||||
const ImGuiID scrollbar_id = (is_multiline && state != NULL) ? GetWindowScrollbarID(draw_window, ImGuiAxis_Y) : 0;
|
||||
const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == scrollbar_id;
|
||||
const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == scrollbar_id;
|
||||
@@ -4856,7 +4876,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
state->CursorAnimReset();
|
||||
|
||||
// Backup state of deactivating item so they'll have a chance to do a write to output buffer on the same frame they report IsItemDeactivatedAfterEdit (#4714)
|
||||
InputTextDeactivateHook(state->ID);
|
||||
if (state->ID != id && state->ID == g.ActiveId && (init_make_active && g.ActiveId != id)) //-V560
|
||||
InputTextDeactivateHook(state->ID); // <-- this is essentially an earlier call to what SetActiveID() would do below.
|
||||
|
||||
// Take a copy of the initial buffer value.
|
||||
// From the moment we focused we are normally ignoring the content of 'buf' (unless we are in read-only mode)
|
||||
@@ -5180,7 +5201,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
if (!is_new_line)
|
||||
{
|
||||
validated = clear_active_id = true;
|
||||
if (io.ConfigInputTextEnterKeepActive && !is_multiline)
|
||||
if (io.ConfigInputTextEnterKeepActive && !is_multiline && !is_ctrl_enter && !is_shift_enter)
|
||||
{
|
||||
// Queue reactivation, so that e.g. IsItemDeactivatedAfterEdit() will work. (#9001)
|
||||
state->SelectAll(); // No need to scroll
|
||||
@@ -5387,18 +5408,33 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
IM_ASSERT(callback_data.BufTextLen == (int)ImStrlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
|
||||
InputTextReconcileUndoState(state, state->CallbackTextBackup.Data, state->CallbackTextBackup.Size - 1, callback_data.Buf, callback_data.BufTextLen);
|
||||
state->TextLen = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen()
|
||||
state->EditedBefore = state->EditedThisFrame = true;
|
||||
state->CursorAnimReset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Will copy result string if modified.
|
||||
// Write back result string if modified.
|
||||
// FIXME-OPT: Could mark dirty state from the stb_textedit callbacks
|
||||
if (!is_readonly && strcmp(state->TextSrc, buf) != 0)
|
||||
if (!is_readonly)
|
||||
{
|
||||
apply_new_text = state->TextSrc;
|
||||
apply_new_text_length = state->TextLen;
|
||||
value_changed = true;
|
||||
if (g.LastItemData.ItemFlags & ImGuiItemFlags_LiveEditOnInputText)
|
||||
{
|
||||
// Apply when modified
|
||||
if (strcmp(state->TextSrc, buf) != 0)
|
||||
{
|
||||
apply_new_text = state->TextSrc;
|
||||
apply_new_text_length = state->TextLen;
|
||||
value_changed = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Apply on validation/deactivation, otherwise cancel out previous apply attempts (e.g. revert)
|
||||
value_changed = ((validated || clear_active_id || revert_edit) && strcmp(state->TextSrc, buf) != 0);
|
||||
apply_new_text = value_changed ? state->TextSrc : NULL;
|
||||
apply_new_text_length = value_changed ? state->TextLen : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5406,13 +5442,15 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
// This is used when e.g. losing focus or tabbing out into another InputText() which may already be using the temp buffer.
|
||||
if (g.InputTextDeactivatedState.ID == id)
|
||||
{
|
||||
if (g.ActiveId != id && IsItemDeactivatedAfterEdit() && !is_readonly && strcmp(g.InputTextDeactivatedState.TextA.Data, buf) != 0)
|
||||
{
|
||||
apply_new_text = g.InputTextDeactivatedState.TextA.Data;
|
||||
apply_new_text_length = g.InputTextDeactivatedState.TextA.Size - 1;
|
||||
value_changed = true;
|
||||
//IMGUI_DEBUG_LOG("InputText(): apply Deactivated data for 0x%08X: \"%.*s\".\n", id, apply_new_text_length, apply_new_text);
|
||||
}
|
||||
// The state only exists after an Edit. IsItemDeactivatedAfterEdit() is not valid in every code path (see "widgets_inputtext_status_noliveedit" test).
|
||||
if ((g.ActiveId != id && IsItemDeactivated()) || (g.ActiveId == id && (flags & ImGuiInputTextFlags_TempInput)))
|
||||
if (!is_readonly && strcmp(g.InputTextDeactivatedState.TextA.Data, buf) != 0)
|
||||
{
|
||||
apply_new_text = g.InputTextDeactivatedState.TextA.Data;
|
||||
apply_new_text_length = g.InputTextDeactivatedState.TextA.Size - 1;
|
||||
value_changed = true;
|
||||
//IMGUI_DEBUG_LOG("InputText(): apply Deactivated data for 0x%08X: \"%.*s\".\n", id, apply_new_text_length, apply_new_text);
|
||||
}
|
||||
g.InputTextDeactivatedState.ID = 0;
|
||||
}
|
||||
|
||||
@@ -5452,7 +5490,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
// Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value)
|
||||
// Otherwise request text input ahead for next frame.
|
||||
if (g.ActiveId == id && clear_active_id)
|
||||
{
|
||||
state->ID = 0; // To avoid InputTextDeactivateHook() unnecessarily running, which wouldn't be harmful but wasteful.
|
||||
ClearActiveID();
|
||||
state->ID = id;
|
||||
}
|
||||
|
||||
// Render frame
|
||||
if (!is_multiline)
|
||||
@@ -5673,7 +5715,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
{
|
||||
// For focus requests to work on our multiline we need to ensure our child ItemAdd() call specifies the ImGuiItemFlags_Inputable (see #4761, #7870)...
|
||||
Dummy(ImVec2(0.0f, text_size_y + style.FramePadding.y));
|
||||
g.NextItemData.ItemFlags |= (ImGuiItemFlags)ImGuiItemFlags_Inputable | ImGuiItemFlags_NoTabStop;
|
||||
g.NextItemData.ItemFlagsSet |= (ImGuiItemFlags)ImGuiItemFlags_Inputable | ImGuiItemFlags_NoTabStop;
|
||||
EndChild();
|
||||
item_data_backup.StatusFlags |= (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredWindow);
|
||||
|
||||
@@ -6087,7 +6129,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
ImGuiIO& io = g.IO;
|
||||
|
||||
const float width = CalcItemWidth();
|
||||
const bool is_readonly = ((g.NextItemData.ItemFlags | g.CurrentItemFlags) & ImGuiItemFlags_ReadOnly) != 0;
|
||||
const bool is_readonly = ((g.NextItemData.ItemFlagsSet | g.CurrentItemFlags) & ImGuiItemFlags_ReadOnly) != 0;
|
||||
g.NextItemData.ClearFlags();
|
||||
|
||||
PushID(label);
|
||||
@@ -8230,7 +8272,7 @@ void ImGui::SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_d
|
||||
if (ImGuiMultiSelectTempData* ms = g.CurrentMultiSelect)
|
||||
{
|
||||
// Auto updating RangeSrcPassedBy for cases were clipper is not used (done before ItemAdd() clipping)
|
||||
g.NextItemData.ItemFlags |= ImGuiItemFlags_HasSelectionUserData | ImGuiItemFlags_IsMultiSelect;
|
||||
g.NextItemData.ItemFlagsSet |= ImGuiItemFlags_HasSelectionUserData | ImGuiItemFlags_IsMultiSelect;
|
||||
if (ms->IO.RangeSrcItem == selection_user_data)
|
||||
ms->RangeSrcPassedBy = true;
|
||||
//ms->PrevSubmittedItem = ms->CurrSubmittedItem; // Can't rely on previous g.NextItemData.SelectionUserData because NextItemData is not restored on nested multi-select.
|
||||
@@ -8238,7 +8280,7 @@ void ImGui::SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_d
|
||||
}
|
||||
else
|
||||
{
|
||||
g.NextItemData.ItemFlags |= ImGuiItemFlags_HasSelectionUserData;
|
||||
g.NextItemData.ItemFlagsSet |= ImGuiItemFlags_HasSelectionUserData;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9398,7 +9440,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
// This is only done for items for the menu set and not the full parent window.
|
||||
const bool menuset_is_open = IsRootOfOpenMenuSet();
|
||||
if (menuset_is_open)
|
||||
g.NextItemData.ItemFlags |= ImGuiItemFlags_NoWindowHoverableCheck;
|
||||
g.NextItemData.ItemFlagsSet |= ImGuiItemFlags_NoWindowHoverableCheck;
|
||||
|
||||
// The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu,
|
||||
// However the final position is going to be different! It is chosen by FindBestWindowPosForPopup().
|
||||
@@ -9623,7 +9665,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
||||
// See BeginMenuEx() for comments about this.
|
||||
const bool menuset_is_open = IsRootOfOpenMenuSet();
|
||||
if (menuset_is_open)
|
||||
g.NextItemData.ItemFlags |= ImGuiItemFlags_NoWindowHoverableCheck;
|
||||
g.NextItemData.ItemFlagsSet |= ImGuiItemFlags_NoWindowHoverableCheck;
|
||||
|
||||
// We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73),
|
||||
// but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only.
|
||||
|
||||
Reference in New Issue
Block a user