Merge branch 'master' into docking

# Conflicts:
#	examples/example_sdl_opengl2/main.cpp
#	examples/example_sdl_opengl3/main.cpp
#	examples/example_sdl_vulkan/main.cpp
#	examples/imgui_impl_sdl.cpp
#	examples/imgui_impl_sdl.h
#	imgui.cpp
This commit is contained in:
omar 2019-04-25 17:53:11 +02:00
commit dfb82d5c22
17 changed files with 194 additions and 109 deletions

View File

@ -110,25 +110,32 @@ Other Changes:
- InputText: Work-around for buggy standard libraries where isprint('\t') returns true. (#2467, #1336) - InputText: Work-around for buggy standard libraries where isprint('\t') returns true. (#2467, #1336)
- InputText: Fixed ImGuiInputTextFlags_AllowTabInput leading to two tabs characters being inserted - InputText: Fixed ImGuiInputTextFlags_AllowTabInput leading to two tabs characters being inserted
if the back-end provided both Key and Character input. (#2467, #1336) if the back-end provided both Key and Character input. (#2467, #1336)
- Added SetNextItemWidth() helper to avoid using PushItemWidth/PopItemWidth() for single items. - Layout: Added SetNextItemWidth() helper to avoid using PushItemWidth/PopItemWidth() for single items.
Note that SetNextItemWidth() currently only affect the same subset of items as PushItemWidth(), Note that SetNextItemWidth() currently only affect the same subset of items as PushItemWidth(),
generally referred to as the large framed+labeled items. generally referred to as the large framed+labeled items. Because the new SetNextItemWidth()
Because the new SetNextItemWidth() function is explicit function is explicit we may later extend its effect to more items.
- Layout: Fixed PushItemWidth(-width) for right-side alignment laying out some items (button, listbox, etc.)
with negative sizes if the 'width' argument was smaller than the available width at the time of item
submission.
- Window: Fixed window with the AlwaysAutoResize flag unnecessarily extending their hovering boundaries
by a few pixels (this is used to facilitate resizing from borders when available for a given window).
One of the noticeable minor side effect was that navigating menus would have had a tendency to disable
highlight from parent menu items earlier than necessary while approaching the child menu.
- Window: Close button is horizontally aligned with style.FramePadding.x.
- GetMouseDragDelta(): also returns the delta on the mouse button released frame. (#2419) - GetMouseDragDelta(): also returns the delta on the mouse button released frame. (#2419)
- GetMouseDragDelta(): verify that mouse positions are valid otherwise returns zero. - GetMouseDragDelta(): verify that mouse positions are valid otherwise returns zero.
- Inputs: Also add support for horizontal scroll with Shift+Mouse Wheel. (#2424, #1463) [@LucaRood] - Inputs: Also add support for horizontal scroll with Shift+Mouse Wheel. (#2424, #1463) [@LucaRood]
- PlotLines, PlotHistogram: Ignore NaN values when calculating min/max bounds. (#2485) - PlotLines, PlotHistogram: Ignore NaN values when calculating min/max bounds. (#2485)
- Window: Window close button is horizontally aligned with style.FramePadding.x.
- Columns: Fixed boundary of clipping being off by 1 pixel within the left column. - Columns: Fixed boundary of clipping being off by 1 pixel within the left column.
- Combo, Slider, Scrollbar: Improve rendering in situation when there's only a few pixels available (<3 pixels). - Combo, Slider, Scrollbar: Improve rendering in situation when there's only a few pixels available (<3 pixels).
- Misc: Fixed PushItemWidth(-width) (for right-side alignment) laying out certain items (button, listbox, etc.) - Nav: Fixed Drag/Slider functions going into text input mode when keyboard CTRL is held while pressing NavActivate.
with negative sizes if the 'width' argument was smaller than the available width at the time of item submission,
- Misc: Added IM_MALLOC/IM_FREE macros mimicking IM_NEW/IM_DELETE so user doesn't need to revert - Misc: Added IM_MALLOC/IM_FREE macros mimicking IM_NEW/IM_DELETE so user doesn't need to revert
to using the ImGui::MemAlloc()/MemFree() calls directly. to using the ImGui::MemAlloc()/MemFree() calls directly.
- Metrics: Added "Show windows rectangles" tool to visualize the different rectangles. - Metrics: Added "Show windows rectangles" tool to visualize the different rectangles.
- Examples: OpenGL: Added a dummy GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized - Examples: OpenGL: Added a dummy GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized
GL function loaders early, and help users understand what they are missing. (#2421) GL function loaders early, and help users understand what they are missing. (#2421)
- Examples: Emscripten: Added Emscripten+SDL+GLES2 example. (#2494, #2492, #2351, #336) [@nicolasnoble] - Examples: Emscripten: Added Emscripten+SDL+GLES2 example. (#2494, #2492, #2351, #336) [@nicolasnoble, @redblobgames]
- Examples: SDL: Added support for SDL_GameController gamepads (enable with ImGuiConfigFlags_NavEnableGamepad). (#2509) [@DJLink]
- Examples: OpenGL3: Minor tweaks + not calling glBindBuffer more than necessary in the render loop. - Examples: OpenGL3: Minor tweaks + not calling glBindBuffer more than necessary in the render loop.
- Examples: Vulkan: Fixed in-flight buffers issues when using multi-viewports. (#2461, #2348, #2378, #2097) - Examples: Vulkan: Fixed in-flight buffers issues when using multi-viewports. (#2461, #2348, #2378, #2097)
- Examples: Vulkan: Added missing support for 32-bit indices (#define ImDrawIdx unsigned int). - Examples: Vulkan: Added missing support for 32-bit indices (#define ImDrawIdx unsigned int).
@ -281,7 +288,7 @@ Other Changes:
- Examples: Win32: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created - Examples: Win32: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created
in a different thread or parent. (#1951, #2087, #2156, #2232) [many people] in a different thread or parent. (#1951, #2087, #2156, #2232) [many people]
- Examples: SDL: Using the SDL_WINDOW_ALLOW_HIGHDPI flag. (#2306, #1676) [@rasky] - Examples: SDL: Using the SDL_WINDOW_ALLOW_HIGHDPI flag. (#2306, #1676) [@rasky]
- Examples: Win32: Added support for XInput games (if ImGuiConfigFlags_NavEnableGamepad is enabled). - Examples: Win32: Added support for XInput gamepads (if ImGuiConfigFlags_NavEnableGamepad is enabled).
- Examples: Win32: Added support for mouse buttons 4 and 5 via WM_XBUTTON* messages. (#2264) - Examples: Win32: Added support for mouse buttons 4 and 5 via WM_XBUTTON* messages. (#2264)
- Examples: DirectX9: Explicitly disable fog (D3DRS_FOGENABLE) before drawing in case user state has it set. (#2288, #2230) - Examples: DirectX9: Explicitly disable fog (D3DRS_FOGENABLE) before drawing in case user state has it set. (#2288, #2230)
- Examples: OpenGL2: Added #define GL_SILENCE_DEPRECATION to cope with newer XCode warnings. - Examples: OpenGL2: Added #define GL_SILENCE_DEPRECATION to cope with newer XCode warnings.

View File

@ -170,7 +170,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- image/image button: misalignment on padded/bordered button? - image/image button: misalignment on padded/bordered button?
- image/image button: parameters are confusing, image() has tint_col,border_col whereas imagebutton() has bg_col/tint_col. Even thou they are different parameters ordering could be more consistent. can we fix that? - image/image button: parameters are confusing, image() has tint_col,border_col whereas imagebutton() has bg_col/tint_col. Even thou they are different parameters ordering could be more consistent. can we fix that?
- image button: not taking an explicit id can be problematic. (#2464, #1390) - image button: not taking an explicit id can be problematic. (#2464, #1390)
- slider/drag: ctrl+click when format doesn't include a % character.. disable? display underlying value in default format? (see InputScalarAsWidgetReplacement) - slider/drag: ctrl+click when format doesn't include a % character.. disable? display underlying value in default format? (see TempInputTextScalar)
- slider: allow using the [-]/[+] buttons used by InputFloat()/InputInt() - slider: allow using the [-]/[+] buttons used by InputFloat()/InputInt()
- slider: initial absolute click is imprecise. change to relative movement slider (same as scrollbar). (#1946) - slider: initial absolute click is imprecise. change to relative movement slider (same as scrollbar). (#1946)
- slider: add dragging-based widgets to edit values with mouse (on 2 axises), saving screen real-estate. - slider: add dragging-based widgets to edit values with mouse (on 2 axises), saving screen real-estate.
@ -234,6 +234,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- tree node / selectable render mismatch which is visible if you use them both next to each other (e.g. cf. property viewer) - tree node / selectable render mismatch which is visible if you use them both next to each other (e.g. cf. property viewer)
- tree node: tweak color scheme to distinguish headers from selected tree node (#581) - tree node: tweak color scheme to distinguish headers from selected tree node (#581)
- tree node: leaf/non-leaf highlight mismatch. - tree node: leaf/non-leaf highlight mismatch.
- tree node: _NoIndentOnOpen flag? would require to store a per-depth bit mask to store info for pop (or whatever is cheaper)
- settings: write more decent code to allow saving/loading new fields: columns, selected tree nodes? - settings: write more decent code to allow saving/loading new fields: columns, selected tree nodes?
- settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file (#437) - settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file (#437)

View File

@ -25,7 +25,7 @@ void main_loop(void*);
int main(int, char**) int main(int, char**)
{ {
// Setup SDL // Setup SDL
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{ {
printf("Error: %s\n", SDL_GetError()); printf("Error: %s\n", SDL_GetError());
return -1; return -1;
@ -62,6 +62,7 @@ int main(int, char**)
ImGui::CreateContext(); ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io; ImGuiIO& io = ImGui::GetIO(); (void)io;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
// For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file. // For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file.
// You may manually call LoadIniSettingsFromMemory() to load settings from your own storage. // You may manually call LoadIniSettingsFromMemory() to load settings from your own storage.

View File

@ -16,7 +16,7 @@
int main(int, char**) int main(int, char**)
{ {
// Setup SDL // Setup SDL
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{ {
printf("Error: %s\n", SDL_GetError()); printf("Error: %s\n", SDL_GetError());
return -1; return -1;
@ -28,8 +28,6 @@ int main(int, char**)
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_DisplayMode current;
SDL_GetCurrentDisplayMode(0, &current);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
SDL_GLContext gl_context = SDL_GL_CreateContext(window); SDL_GLContext gl_context = SDL_GL_CreateContext(window);
@ -41,6 +39,7 @@ int main(int, char**)
ImGui::CreateContext(); ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io; ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigViewportsNoAutoMerge = true; //io.ConfigViewportsNoAutoMerge = true;

View File

@ -25,7 +25,7 @@
int main(int, char**) int main(int, char**)
{ {
// Setup SDL // Setup SDL
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{ {
printf("Error: %s\n", SDL_GetError()); printf("Error: %s\n", SDL_GetError());
return -1; return -1;
@ -52,8 +52,6 @@ int main(int, char**)
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_DisplayMode current;
SDL_GetCurrentDisplayMode(0, &current);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
SDL_GLContext gl_context = SDL_GL_CreateContext(window); SDL_GLContext gl_context = SDL_GL_CreateContext(window);
@ -81,6 +79,7 @@ int main(int, char**)
ImGui::CreateContext(); ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io; ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigViewportsNoAutoMerge = true; //io.ConfigViewportsNoAutoMerge = true;

View File

@ -319,15 +319,13 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd)
int main(int, char**) int main(int, char**)
{ {
// Setup SDL // Setup SDL
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{ {
printf("Error: %s\n", SDL_GetError()); printf("Error: %s\n", SDL_GetError());
return 1; return 1;
} }
// Setup window // Setup window
SDL_DisplayMode current;
SDL_GetCurrentDisplayMode(0, &current);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+Vulkan example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+Vulkan example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
@ -358,6 +356,7 @@ int main(int, char**)
ImGui::CreateContext(); ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io; ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoTaskBarIcons; //io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoTaskBarIcons;

View File

@ -385,7 +385,7 @@ void ImGui_ImplGlfw_NewFrame()
ImGui_ImplGlfw_UpdateMousePosAndButtons(); ImGui_ImplGlfw_UpdateMousePosAndButtons();
ImGui_ImplGlfw_UpdateMouseCursor(); ImGui_ImplGlfw_UpdateMouseCursor();
// Gamepad navigation mapping // Update game controllers (if enabled and available)
ImGui_ImplGlfw_UpdateGamepads(); ImGui_ImplGlfw_UpdateGamepads();
} }

View File

@ -6,6 +6,7 @@
// Issues: // Issues:
// [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I // [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I
// [ ] Platform: Missing mouse cursor shape/visibility support.
// [ ] Platform: Missing clipboard support (not supported by Glut). // [ ] Platform: Missing clipboard support (not supported by Glut).
// [ ] Platform: Missing gamepad support. // [ ] Platform: Missing gamepad support.

View File

@ -6,6 +6,7 @@
// Issues: // Issues:
// [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I // [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I
// [ ] Platform: Missing mouse cursor shape/visibility support.
// [ ] Platform: Missing clipboard support (not supported by Glut). // [ ] Platform: Missing clipboard support (not supported by Glut).
// [ ] Platform: Missing gamepad support. // [ ] Platform: Missing gamepad support.

View File

@ -7,10 +7,10 @@
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Clipboard support. // [X] Platform: Clipboard support.
// [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE). // [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE).
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// Missing features: // Missing features:
// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. // [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
// [ ] Platform: Gamepad support (need to use SDL_GameController API to fill the io.NavInputs[] value when ImGuiConfigFlags_NavEnableGamepad is set).
// [ ] Platform: Multi-viewport + Minimized windows seems to break mouse wheel events (at least under Windows). // [ ] Platform: Multi-viewport + Minimized windows seems to break mouse wheel events (at least under Windows).
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
@ -20,6 +20,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2019-04-23: Inputs: Added support for SDL_GameController (if ImGuiConfigFlags_NavEnableGamepad is set by user application).
// 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized. // 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.
// 2018-12-21: Inputs: Workaround for Android/iOS which don't seem to handle focus related calls. // 2018-12-21: Inputs: Workaround for Android/iOS which don't seem to handle focus related calls.
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window. // 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
@ -325,6 +326,47 @@ static void ImGui_ImplSDL2_UpdateMouseCursor()
} }
} }
static void ImGui_ImplSDL2_UpdateGamepads()
{
ImGuiIO& io = ImGui::GetIO();
memset(io.NavInputs, 0, sizeof(io.NavInputs));
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
return;
// Get gamepad
SDL_GameController* game_controller = SDL_GameControllerOpen(0);
if (!game_controller)
{
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
return;
}
// Update gamepad inputs
#define MAP_BUTTON(NAV_NO, BUTTON_NO) { io.NavInputs[NAV_NO] = (SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0) ? 1.0f : 0.0f; }
#define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; }
const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value.
MAP_BUTTON(ImGuiNavInput_Activate, SDL_CONTROLLER_BUTTON_A); // Cross / A
MAP_BUTTON(ImGuiNavInput_Cancel, SDL_CONTROLLER_BUTTON_B); // Circle / B
MAP_BUTTON(ImGuiNavInput_Menu, SDL_CONTROLLER_BUTTON_X); // Square / X
MAP_BUTTON(ImGuiNavInput_Input, SDL_CONTROLLER_BUTTON_Y); // Triangle / Y
MAP_BUTTON(ImGuiNavInput_DpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT); // D-Pad Left
MAP_BUTTON(ImGuiNavInput_DpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); // D-Pad Right
MAP_BUTTON(ImGuiNavInput_DpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP); // D-Pad Up
MAP_BUTTON(ImGuiNavInput_DpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN); // D-Pad Down
MAP_BUTTON(ImGuiNavInput_FocusPrev, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB
MAP_BUTTON(ImGuiNavInput_FocusNext, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB
MAP_BUTTON(ImGuiNavInput_TweakSlow, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB
MAP_BUTTON(ImGuiNavInput_TweakFast, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB
MAP_ANALOG(ImGuiNavInput_LStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiNavInput_LStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiNavInput_LStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32767);
MAP_ANALOG(ImGuiNavInput_LStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767);
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
#undef MAP_BUTTON
#undef MAP_ANALOG
}
void ImGui_ImplSDL2_NewFrame(SDL_Window* window) void ImGui_ImplSDL2_NewFrame(SDL_Window* window)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
@ -347,6 +389,9 @@ void ImGui_ImplSDL2_NewFrame(SDL_Window* window)
ImGui_ImplSDL2_UpdateMousePosAndButtons(); ImGui_ImplSDL2_UpdateMousePosAndButtons();
ImGui_ImplSDL2_UpdateMouseCursor(); ImGui_ImplSDL2_UpdateMouseCursor();
// Update game controllers (if enabled and available)
ImGui_ImplSDL2_UpdateGamepads();
} }
//-------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------

View File

@ -6,10 +6,11 @@
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Clipboard support. // [X] Platform: Clipboard support.
// [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE). // [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE).
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// Missing features: // Missing features:
// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. // [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
// [ ] Platform: Gamepad support (need to use SDL_GameController API to fill the io.NavInputs[] value when ImGuiConfigFlags_NavEnableGamepad is set). // [ ] Platform: Multi-viewport + Minimized windows seems to break mouse wheel events (at least under Windows).
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.

View File

@ -286,7 +286,7 @@ void ImGui_ImplWin32_NewFrame()
ImGui_ImplWin32_UpdateMouseCursor(); ImGui_ImplWin32_UpdateMouseCursor();
} }
// Update game controllers (if available) // Update game controllers (if enabled and available)
ImGui_ImplWin32_UpdateGamepads(); ImGui_ImplWin32_UpdateGamepads();
} }

View File

@ -404,8 +404,9 @@ CODE
- 2018/07/22 (1.63) - changed ImGui::GetTime() return value from float to double to avoid accumulating floating point imprecisions over time. - 2018/07/22 (1.63) - changed ImGui::GetTime() return value from float to double to avoid accumulating floating point imprecisions over time.
- 2018/07/08 (1.63) - style: renamed ImGuiCol_ModalWindowDarkening to ImGuiCol_ModalWindowDimBg for consistency with other features. Kept redirection enum (will obsolete). - 2018/07/08 (1.63) - style: renamed ImGuiCol_ModalWindowDarkening to ImGuiCol_ModalWindowDimBg for consistency with other features. Kept redirection enum (will obsolete).
- 2018/06/08 (1.62) - examples: the imgui_impl_xxx files have been split to separate platform (Win32, Glfw, SDL2, etc.) from renderer (DX11, OpenGL, Vulkan, etc.). - 2018/06/08 (1.62) - examples: the imgui_impl_xxx files have been split to separate platform (Win32, Glfw, SDL2, etc.) from renderer (DX11, OpenGL, Vulkan, etc.).
old binding will still work as is, however prefer using the separated bindings as they will be updated to be multi-viewport conformant. old bindings will still work as is, however prefer using the separated bindings as they will be updated to support multi-viewports.
when adopting new bindings follow the main.cpp code of your preferred examples/ folder to know which functions to call. when adopting new bindings follow the main.cpp code of your preferred examples/ folder to know which functions to call.
in particular, note that old bindings called ImGui::NewFrame() at the end of their ImGui_ImplXXXX_NewFrame() function.
- 2018/06/06 (1.62) - renamed GetGlyphRangesChinese() to GetGlyphRangesChineseFull() to distinguish other variants and discourage using the full set. - 2018/06/06 (1.62) - renamed GetGlyphRangesChinese() to GetGlyphRangesChineseFull() to distinguish other variants and discourage using the full set.
- 2018/06/06 (1.62) - TreeNodeEx()/TreeNodeBehavior(): the ImGuiTreeNodeFlags_CollapsingHeader helper now include the ImGuiTreeNodeFlags_NoTreePushOnOpen flag. See Changelog for details. - 2018/06/06 (1.62) - TreeNodeEx()/TreeNodeBehavior(): the ImGuiTreeNodeFlags_CollapsingHeader helper now include the ImGuiTreeNodeFlags_NoTreePushOnOpen flag. See Changelog for details.
- 2018/05/03 (1.61) - DragInt(): the default compile-time format string has been changed from "%.0f" to "%d", as we are not using integers internally any more. - 2018/05/03 (1.61) - DragInt(): the default compile-time format string has been changed from "%.0f" to "%d", as we are not using integers internally any more.
@ -3691,8 +3692,8 @@ void ImGui::NewFrame()
g.ActiveIdIsAlive = 0; g.ActiveIdIsAlive = 0;
g.ActiveIdPreviousFrameIsAlive = false; g.ActiveIdPreviousFrameIsAlive = false;
g.ActiveIdIsJustActivated = false; g.ActiveIdIsJustActivated = false;
if (g.ScalarAsInputTextId && g.ActiveId != g.ScalarAsInputTextId) if (g.TempInputTextId != 0 && g.ActiveId != g.TempInputTextId)
g.ScalarAsInputTextId = 0; g.TempInputTextId = 0;
// Drag and drop // Drag and drop
g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr; g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr;
@ -4362,7 +4363,7 @@ static void FindHoveredWindow()
// Using the clipped AABB, a child window will typically be clipped by its parent (not always) // Using the clipped AABB, a child window will typically be clipped by its parent (not always)
ImRect bb(window->OuterRectClipped); ImRect bb(window->OuterRectClipped);
if ((window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_NoResize)) if (window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize))
bb.Expand(padding_regular); bb.Expand(padding_regular);
else else
bb.Expand(padding_for_resize_from_edges); bb.Expand(padding_for_resize_from_edges);
@ -5944,7 +5945,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->DC.TextWrapPosStack.resize(0); window->DC.TextWrapPosStack.resize(0);
window->DC.CurrentColumns = NULL; window->DC.CurrentColumns = NULL;
window->DC.TreeDepth = 0; window->DC.TreeDepth = 0;
window->DC.TreeDepthMayJumpToParentOnPop = 0x00; window->DC.TreeStoreMayJumpToParentOnPop = 0x00;
window->DC.StateStorage = &window->StateStorage; window->DC.StateStorage = &window->StateStorage;
window->DC.GroupStack.resize(0); window->DC.GroupStack.resize(0);
window->MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user); window->MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user);
@ -6579,7 +6580,7 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, float val)
*pvar = val; *pvar = val;
return; return;
} }
IM_ASSERT(0); // Called function with wrong-type? Variable is not a float. IM_ASSERT(0 && "Called PushStyleVar() float variant but variable is not a float!");
} }
void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)
@ -6593,7 +6594,7 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)
*pvar = val; *pvar = val;
return; return;
} }
IM_ASSERT(0); // Called function with wrong-type? Variable is not a ImVec2. IM_ASSERT(0 && "Called PushStyleVar() ImVec2 variant but variable is not a ImVec2!");
} }
void ImGui::PopStyleVar(int count) void ImGui::PopStyleVar(int count)
@ -7021,7 +7022,7 @@ void ImGui::SetNextWindowClass(const ImGuiWindowClass* window_class)
g.NextWindowData.WindowClass = *window_class; g.NextWindowData.WindowClass = *window_class;
} }
// FIXME: This is in window space (not screen space!) // FIXME: This is in window space (not screen space!). We should try to obsolete all those functions.
ImVec2 ImGui::GetContentRegionMax() ImVec2 ImGui::GetContentRegionMax()
{ {
ImGuiWindow* window = GImGui->CurrentWindow; ImGuiWindow* window = GImGui->CurrentWindow;
@ -7320,6 +7321,13 @@ void ImGui::PushID(int int_id)
window->IDStack.push_back(window->GetIDNoKeepAlive(ptr_id)); window->IDStack.push_back(window->GetIDNoKeepAlive(ptr_id));
} }
// Push a given id value ignoring the ID stack as a seed.
void ImGui::PushOverrideID(ImGuiID id)
{
ImGuiWindow* window = GImGui->CurrentWindow;
window->IDStack.push_back(id);
}
void ImGui::PopID() void ImGui::PopID()
{ {
ImGuiWindow* window = GImGui->CurrentWindow; ImGuiWindow* window = GImGui->CurrentWindow;

15
imgui.h
View File

@ -48,7 +48,7 @@ Index of this file:
// Version // Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.70 WIP" #define IMGUI_VERSION "1.70 WIP"
#define IMGUI_VERSION_NUM 16990 #define IMGUI_VERSION_NUM 16991
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert)) #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert))
#define IMGUI_HAS_VIEWPORT 1 // Viewport WIP branch #define IMGUI_HAS_VIEWPORT 1 // Viewport WIP branch
#define IMGUI_HAS_DOCK 1 // Docking WIP branch #define IMGUI_HAS_DOCK 1 // Docking WIP branch
@ -221,10 +221,10 @@ namespace ImGui
// Main // Main
IMGUI_API ImGuiIO& GetIO(); // access the IO structure (mouse/keyboard/gamepad inputs, time, various configuration options/flags) IMGUI_API ImGuiIO& GetIO(); // access the IO structure (mouse/keyboard/gamepad inputs, time, various configuration options/flags)
IMGUI_API ImGuiStyle& GetStyle(); // access the Style structure (colors, sizes). Always use PushStyleCol(), PushStyleVar() to modify style mid-frame. IMGUI_API ImGuiStyle& GetStyle(); // access the Style structure (colors, sizes). Always use PushStyleCol(), PushStyleVar() to modify style mid-frame.
IMGUI_API void NewFrame(); // start a new ImGui frame, you can submit any command from this point until Render()/EndFrame(). IMGUI_API void NewFrame(); // start a new Dear ImGui frame, you can submit any command from this point until Render()/EndFrame().
IMGUI_API void EndFrame(); // ends the ImGui frame. automatically called by Render(), you likely don't need to call that yourself directly. If you don't need to render data (skipping rendering) you may call EndFrame() but you'll have wasted CPU already! If you don't need to render, better to not create any imgui windows and not call NewFrame() at all! IMGUI_API void EndFrame(); // ends the Dear ImGui frame. automatically called by Render(), you likely don't need to call that yourself directly. If you don't need to render data (skipping rendering) you may call EndFrame() but you'll have wasted CPU already! If you don't need to render, better to not create any imgui windows and not call NewFrame() at all!
IMGUI_API void Render(); // ends the ImGui frame, finalize the draw data. (Obsolete: optionally call io.RenderDrawListsFn if set. Nowadays, prefer calling your render function yourself.) IMGUI_API void Render(); // ends the Dear ImGui frame, finalize the draw data. You can get call GetDrawData() to obtain it and run your rendering function. (Obsolete: this used to call io.RenderDrawListsFn(). Nowadays, we allow and prefer calling your render function yourself.)
IMGUI_API ImDrawData* GetDrawData(); // valid after Render() and until the next call to NewFrame(). this is what you have to render. (Obsolete: this used to be passed to your io.RenderDrawListsFn() function.) IMGUI_API ImDrawData* GetDrawData(); // valid after Render() and until the next call to NewFrame(). this is what you have to render.
// Demo, Debug, Information // Demo, Debug, Information
IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create demo/test window (previously called ShowTestWindow). demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application! IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create demo/test window (previously called ShowTestWindow). demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application!
@ -823,7 +823,7 @@ enum ImGuiTreeNodeFlags_
ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes).
ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow
ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding(). ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding().
//ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 11, // FIXME: TODO: Extend hit box horizontally even if not framed //ImGuiTreeNodeFlags_SpanAllAvailWidth = 1 << 11, // FIXME: TODO: Extend hit box horizontally even if not framed
//ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 12, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 12, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible
ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 13, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop) ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 13, // (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 ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog
@ -2013,7 +2013,8 @@ struct ImDrawList
}; };
// All draw data to render an ImGui frame // All draw data to render an ImGui frame
// (NB: the style and the naming convention here is a little inconsistent but we preserve them for backward compatibility purpose) // (NB: the style and the naming convention here is a little inconsistent, we currently preserve them for backward compatibility purpose,
// as this is one of the oldest structure exposed by the library! Basically, ImDrawList == CmdList)
struct ImDrawData struct ImDrawData
{ {
bool Valid; // Only valid after Render() is called and before the next NewFrame() is called. bool Valid; // Only valid after Render() is called and before the next NewFrame() is called.

View File

@ -2425,6 +2425,13 @@ static void ShowDemoWindowColumns()
ImGui::PushID("Columns"); ImGui::PushID("Columns");
static bool disable_indent = false;
ImGui::Checkbox("Disable tree indentation", &disable_indent);
ImGui::SameLine();
HelpMarker("Disable the indenting of tree nodes so demo columns can use the full window width.");
if (disable_indent)
ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, 0.0f);
// Basic columns // Basic columns
if (ImGui::TreeNode("Basic")) if (ImGui::TreeNode("Basic"))
{ {
@ -2530,7 +2537,10 @@ static void ShowDemoWindowColumns()
if (h_borders && ImGui::GetColumnIndex() == 0) if (h_borders && ImGui::GetColumnIndex() == 0)
ImGui::Separator(); ImGui::Separator();
ImGui::Text("%c%c%c", 'a'+i, 'a'+i, 'a'+i); ImGui::Text("%c%c%c", 'a'+i, 'a'+i, 'a'+i);
ImGui::Text("Width %.2f\nOffset %.2f", ImGui::GetColumnWidth(), ImGui::GetColumnOffset()); ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
ImGui::Text("Offset %.2f", ImGui::GetColumnOffset());
ImGui::Text("Long text that is likely to clip");
ImGui::Button("Button", ImVec2(-1.0f, 0.0f));
ImGui::NextColumn(); ImGui::NextColumn();
} }
ImGui::Columns(1); ImGui::Columns(1);
@ -2598,6 +2608,9 @@ static void ShowDemoWindowColumns()
ImGui::Separator(); ImGui::Separator();
ImGui::TreePop(); ImGui::TreePop();
} }
if (disable_indent)
ImGui::PopStyleVar();
ImGui::PopID(); ImGui::PopID();
} }

View File

@ -1081,7 +1081,7 @@ struct ImGuiContext
// Widget state // Widget state
ImGuiInputTextState InputTextState; ImGuiInputTextState InputTextState;
ImFont InputTextPasswordFont; ImFont InputTextPasswordFont;
ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiID TempInputTextId; // Temporary text input when CTRL+clicking on a slider, etc.
ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
ImVec4 ColorPickerRef; ImVec4 ColorPickerRef;
bool DragCurrentAccumDirty; bool DragCurrentAccumDirty;
@ -1226,7 +1226,7 @@ struct ImGuiContext
CurrentTabBar = NULL; CurrentTabBar = NULL;
ScalarAsInputTextId = 0; TempInputTextId = 0;
ColorEditOptions = ImGuiColorEditFlags__OptionsDefault; ColorEditOptions = ImGuiColorEditFlags__OptionsDefault;
DragCurrentAccumDirty = false; DragCurrentAccumDirty = false;
DragCurrentAccum = 0.0f; DragCurrentAccum = 0.0f;
@ -1277,7 +1277,7 @@ struct IMGUI_API ImGuiWindowTempData
ImVec2 PrevLineSize; ImVec2 PrevLineSize;
float PrevLineTextBaseOffset; float PrevLineTextBaseOffset;
int TreeDepth; int TreeDepth;
ImU32 TreeDepthMayJumpToParentOnPop; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31 ImU32 TreeStoreMayJumpToParentOnPop; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31.. Could be turned into a ImU64 if necessary.
ImGuiID LastItemId; ImGuiID LastItemId;
ImGuiItemStatusFlags LastItemStatusFlags; ImGuiItemStatusFlags LastItemStatusFlags;
ImRect LastItemRect; // Interaction rect ImRect LastItemRect; // Interaction rect
@ -1319,7 +1319,7 @@ struct IMGUI_API ImGuiWindowTempData
CurrentLineSize = PrevLineSize = ImVec2(0.0f, 0.0f); CurrentLineSize = PrevLineSize = ImVec2(0.0f, 0.0f);
CurrentLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f; CurrentLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f;
TreeDepth = 0; TreeDepth = 0;
TreeDepthMayJumpToParentOnPop = 0x00; TreeStoreMayJumpToParentOnPop = 0x00;
LastItemId = 0; LastItemId = 0;
LastItemStatusFlags = 0; LastItemStatusFlags = 0;
LastItemRect = LastItemDisplayRect = ImRect(); LastItemRect = LastItemDisplayRect = ImRect();
@ -1618,6 +1618,7 @@ namespace ImGui
IMGUI_API void SetHoveredID(ImGuiID id); IMGUI_API void SetHoveredID(ImGuiID id);
IMGUI_API void KeepAliveID(ImGuiID id); IMGUI_API void KeepAliveID(ImGuiID id);
IMGUI_API void MarkItemEdited(ImGuiID id); IMGUI_API void MarkItemEdited(ImGuiID id);
IMGUI_API void PushOverrideID(ImGuiID id);
// Basic Helpers for widget code // Basic Helpers for widget code
IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f); IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f);
@ -1772,7 +1773,7 @@ namespace ImGui
IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f); IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f);
IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL);
IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging
IMGUI_API void TreePushRawID(ImGuiID id); IMGUI_API void TreePushOverrideID(ImGuiID id);
// Template functions are instantiated in imgui_widgets.cpp for a finite number of types. // Template functions are instantiated in imgui_widgets.cpp for a finite number of types.
// To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036). // To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036).
@ -1784,7 +1785,8 @@ namespace ImGui
// InputText // InputText
IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format); IMGUI_API bool TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format);
inline bool TempInputTextIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputTextId == id); }
// Color // Color
IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags); IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags);

View File

@ -2020,8 +2020,6 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, floa
if (!ItemAdd(total_bb, id, &frame_bb)) if (!ItemAdd(total_bb, id, &frame_bb))
return false; return false;
const bool hovered = ItemHoverable(frame_bb, id);
// Default format string when passing NULL // Default format string when passing NULL
// Patch old "%.0f" format string to use "%d", read function comments for more details. // Patch old "%.0f" format string to use "%d", read function comments for more details.
IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT); IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT);
@ -2031,37 +2029,40 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, floa
format = PatchFormatStringFloatToInt(format); format = PatchFormatStringFloatToInt(format);
// Tabbing or CTRL-clicking on Drag turns it into an input box // Tabbing or CTRL-clicking on Drag turns it into an input box
bool start_text_input = false; const bool hovered = ItemHoverable(frame_bb, id);
const bool focus_requested = FocusableItemRegister(window, id); bool temp_input_is_active = TempInputTextIsActive(id);
if (focus_requested || (hovered && (g.IO.MouseClicked[0] || g.IO.MouseDoubleClicked[0])) || g.NavActivateId == id || (g.NavInputId == id && g.ScalarAsInputTextId != id)) bool temp_input_start = false;
if (!temp_input_is_active)
{ {
SetActiveID(id, window); const bool focus_requested = FocusableItemRegister(window, id);
SetFocusID(id, window); const bool clicked = (hovered && g.IO.MouseClicked[0]);
FocusWindow(window); const bool double_clicked = (hovered && g.IO.MouseDoubleClicked[0]);
g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); if (focus_requested || clicked || double_clicked || g.NavActivateId == id || g.NavInputId == id)
if (focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0] || g.NavInputId == id)
{ {
start_text_input = true; SetActiveID(id, window);
g.ScalarAsInputTextId = 0; SetFocusID(id, window);
FocusWindow(window);
g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
if (focus_requested || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavInputId == id)
{
temp_input_start = true;
FocusableItemUnregister(window);
}
} }
} }
if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id)) if (temp_input_is_active || temp_input_start)
{ return TempInputTextScalar(frame_bb, id, label, data_type, v, format);
window->DC.CursorPos = frame_bb.Min;
FocusableItemUnregister(window);
return InputScalarAsWidgetReplacement(frame_bb, id, label, data_type, v, format);
}
// Actual drag behavior
const bool value_changed = DragBehavior(id, data_type, v, v_speed, v_min, v_max, format, power, ImGuiDragFlags_None);
if (value_changed)
MarkItemEdited(id);
// Draw frame // Draw frame
const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
RenderNavHighlight(frame_bb, id); RenderNavHighlight(frame_bb, id);
RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding);
// Drag behavior
const bool value_changed = DragBehavior(id, data_type, v, v_speed, v_min, v_max, format, power, ImGuiDragFlags_None);
if (value_changed)
MarkItemEdited(id);
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value. // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
char value_buf[64]; char value_buf[64];
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format); const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format);
@ -2473,27 +2474,28 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, co
format = PatchFormatStringFloatToInt(format); format = PatchFormatStringFloatToInt(format);
// Tabbing or CTRL-clicking on Slider turns it into an input box // Tabbing or CTRL-clicking on Slider turns it into an input box
bool start_text_input = false;
const bool focus_requested = FocusableItemRegister(window, id);
const bool hovered = ItemHoverable(frame_bb, id); const bool hovered = ItemHoverable(frame_bb, id);
if (focus_requested || (hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || (g.NavInputId == id && g.ScalarAsInputTextId != id)) bool temp_input_is_active = TempInputTextIsActive(id);
bool temp_input_start = false;
if (!temp_input_is_active)
{ {
SetActiveID(id, window); const bool focus_requested = FocusableItemRegister(window, id);
SetFocusID(id, window); const bool clicked = (hovered && g.IO.MouseClicked[0]);
FocusWindow(window); if (focus_requested || clicked || g.NavActivateId == id || g.NavInputId == id)
g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
if (focus_requested || g.IO.KeyCtrl || g.NavInputId == id)
{ {
start_text_input = true; SetActiveID(id, window);
g.ScalarAsInputTextId = 0; SetFocusID(id, window);
FocusWindow(window);
g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
if (focus_requested || (clicked && g.IO.KeyCtrl) || g.NavInputId == id)
{
temp_input_start = true;
FocusableItemUnregister(window);
}
} }
} }
if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id)) if (temp_input_is_active || temp_input_start)
{ return TempInputTextScalar(frame_bb, id, label, data_type, v, format);
window->DC.CursorPos = frame_bb.Min;
FocusableItemUnregister(window);
return InputScalarAsWidgetReplacement(frame_bb, id, label, data_type, v, format);
}
// Draw frame // Draw frame
const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
@ -2679,7 +2681,7 @@ bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min,
// - ImParseFormatFindEnd() [Internal] // - ImParseFormatFindEnd() [Internal]
// - ImParseFormatTrimDecorations() [Internal] // - ImParseFormatTrimDecorations() [Internal]
// - ImParseFormatPrecision() [Internal] // - ImParseFormatPrecision() [Internal]
// - InputScalarAsWidgetReplacement() [Internal] // - TempInputTextScalar() [Internal]
// - InputScalar() // - InputScalar()
// - InputScalarN() // - InputScalarN()
// - InputFloat() // - InputFloat()
@ -2765,16 +2767,16 @@ int ImParseFormatPrecision(const char* fmt, int default_precision)
return (precision == INT_MAX) ? default_precision : precision; return (precision == INT_MAX) ? default_precision : precision;
} }
// Create text input in place of an active drag/slider (used when doing a CTRL+Click on drag/slider widgets) // Create text input in place of another active widget (e.g. used when doing a CTRL+Click on drag/slider widgets)
// FIXME: Facilitate using this in variety of other situations. // FIXME: Facilitate using this in variety of other situations.
bool ImGui::InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format) bool ImGui::TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format)
{ {
IM_UNUSED(id);
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
// On the first frame, g.ScalarAsInputTextId == 0, then on subsequent frames it becomes == id. // On the first frame, g.TempInputTextId == 0, then on subsequent frames it becomes == id.
// We clear ActiveID on the first frame to allow the InputText() taking it back. // We clear ActiveID on the first frame to allow the InputText() taking it back.
if (g.ScalarAsInputTextId == 0) const bool init = (g.TempInputTextId != id);
if (init)
ClearActiveID(); ClearActiveID();
char fmt_buf[32]; char fmt_buf[32];
@ -2782,13 +2784,15 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const c
format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf)); format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf));
DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, data_ptr, format); DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, data_ptr, format);
ImStrTrimBlanks(data_buf); ImStrTrimBlanks(data_buf);
g.CurrentWindow->DC.CursorPos = bb.Min;
ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ((data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImGuiInputTextFlags_CharsScientific : ImGuiInputTextFlags_CharsDecimal); ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ((data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImGuiInputTextFlags_CharsScientific : ImGuiInputTextFlags_CharsDecimal);
bool value_changed = InputTextEx(label, NULL, data_buf, IM_ARRAYSIZE(data_buf), bb.GetSize(), flags); bool value_changed = InputTextEx(label, NULL, data_buf, IM_ARRAYSIZE(data_buf), bb.GetSize(), flags);
if (g.ScalarAsInputTextId == 0) if (init)
{ {
// First frame we started displaying the InputText widget, we expect it to take the active id. // First frame we started displaying the InputText widget, we expect it to take the active id.
IM_ASSERT(g.ActiveId == id); IM_ASSERT(g.ActiveId == id);
g.ScalarAsInputTextId = g.ActiveId; g.TempInputTextId = g.ActiveId;
} }
if (value_changed) if (value_changed)
return DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, data_ptr, NULL); return DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, data_ptr, NULL);
@ -5107,7 +5111,7 @@ 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(). // For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop().
// This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero. // This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero.
if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
window->DC.TreeDepthMayJumpToParentOnPop |= (1 << window->DC.TreeDepth); window->DC.TreeStoreMayJumpToParentOnPop |= (1 << window->DC.TreeDepth);
bool item_add = ItemAdd(interact_bb, id); bool item_add = ItemAdd(interact_bb, id);
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HasDisplayRect; window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HasDisplayRect;
@ -5116,7 +5120,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
if (!item_add) if (!item_add)
{ {
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
TreePushRawID(id); TreePushOverrideID(id);
IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0)); IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
return is_open; return is_open;
} }
@ -5220,7 +5224,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
} }
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
TreePushRawID(id); TreePushOverrideID(id);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0)); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
return is_open; return is_open;
} }
@ -5241,7 +5245,7 @@ void ImGui::TreePush(const void* ptr_id)
PushID(ptr_id ? ptr_id : (const void*)"#TreePush"); PushID(ptr_id ? ptr_id : (const void*)"#TreePush");
} }
void ImGui::TreePushRawID(ImGuiID id) void ImGui::TreePushOverrideID(ImGuiID id)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
Indent(); Indent();
@ -5257,12 +5261,12 @@ void ImGui::TreePop()
window->DC.TreeDepth--; window->DC.TreeDepth--;
if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
if (g.NavIdIsAlive && (window->DC.TreeDepthMayJumpToParentOnPop & (1 << window->DC.TreeDepth))) if (g.NavIdIsAlive && (window->DC.TreeStoreMayJumpToParentOnPop & (1 << window->DC.TreeDepth)))
{ {
SetNavID(window->IDStack.back(), g.NavLayer); SetNavID(window->IDStack.back(), g.NavLayer);
NavMoveRequestCancel(); NavMoveRequestCancel();
} }
window->DC.TreeDepthMayJumpToParentOnPop &= (1 << window->DC.TreeDepth) - 1; window->DC.TreeStoreMayJumpToParentOnPop &= (1 << window->DC.TreeDepth) - 1;
IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much. IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much.
PopID(); PopID();
@ -5439,7 +5443,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
bb.Max.x -= (GetContentRegionMax().x - max_x); bb.Max.x -= (GetContentRegionMax().x - max_x);
} }
if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]);
RenderTextClipped(bb_inner.Min, bb_inner.Max, label, NULL, &label_size, style.SelectableTextAlign, &bb); RenderTextClipped(bb_inner.Min, bb_inner.Max, label, NULL, &label_size, style.SelectableTextAlign, &bb);
if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor(); if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor();
@ -5913,10 +5917,11 @@ void ImGui::EndMenuBar()
{ {
// To do so we claim focus back, restore NavId and then process the movement request for yet another frame. // To do so we claim focus back, restore NavId and then process the movement request for yet another frame.
// This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth the hassle/cost) // This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth the hassle/cost)
IM_ASSERT(window->DC.NavLayerActiveMaskNext & 0x02); // Sanity check const ImGuiNavLayer layer = ImGuiNavLayer_Menu;
IM_ASSERT(window->DC.NavLayerActiveMaskNext & (1 << layer)); // Sanity check
FocusWindow(window); FocusWindow(window);
SetNavIDWithRectRel(window->NavLastIds[1], 1, window->NavRectRel[1]); SetNavIDWithRectRel(window->NavLastIds[layer], layer, window->NavRectRel[layer]);
g.NavLayer = ImGuiNavLayer_Menu; g.NavLayer = layer;
g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection. g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection.
g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued; g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued;
NavMoveRequestCancel(); NavMoveRequestCancel();
@ -5966,7 +5971,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
// For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin() // For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin()
popup_pos = ImVec2(pos.x - 1.0f - (float)(int)(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight()); popup_pos = ImVec2(pos.x - 1.0f - (float)(int)(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight());
window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f);
PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
float w = label_size.x; float w = label_size.x;
pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_PressedOnClick | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_PressedOnClick | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f));
PopStyleVar(); PopStyleVar();
@ -6110,7 +6115,7 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo
// Note that in this situation we render neither the shortcut neither the selected tick mark // Note that in this situation we render neither the shortcut neither the selected tick mark
float w = label_size.x; float w = label_size.x;
window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f);
PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
pressed = Selectable(label, false, flags, ImVec2(w, 0.0f)); pressed = Selectable(label, false, flags, ImVec2(w, 0.0f));
PopStyleVar(); PopStyleVar();
window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
@ -6246,7 +6251,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
return false; return false;
if ((flags & ImGuiTabBarFlags_DockNode) == 0) if ((flags & ImGuiTabBarFlags_DockNode) == 0)
window->IDStack.push_back(tab_bar->ID); PushOverrideID(tab_bar->ID);
// Add to stack // Add to stack
g.CurrentTabBarStack.push_back(GetTabBarRefFromTabBar(tab_bar)); g.CurrentTabBarStack.push_back(GetTabBarRefFromTabBar(tab_bar));
@ -6741,7 +6746,8 @@ static ImGuiTabItem* ImGui::TabBarTabListPopupButton(ImGuiTabBar* tab_bar)
bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags flags) bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.CurrentWindow->SkipItems) ImGuiWindow* window = g.CurrentWindow;
if (window->SkipItems)
return false; return false;
ImGuiTabBar* tab_bar = g.CurrentTabBar; ImGuiTabBar* tab_bar = g.CurrentTabBar;
@ -6754,7 +6760,7 @@ bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags f
if (ret && !(flags & ImGuiTabItemFlags_NoPushId)) if (ret && !(flags & ImGuiTabItemFlags_NoPushId))
{ {
ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx]; ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx];
g.CurrentWindow->IDStack.push_back(tab->ID); // We already hashed 'label' so push into the ID stack directly instead of doing another hash through PushID(label) PushOverrideID(tab->ID); // We already hashed 'label' so push into the ID stack directly instead of doing another hash through PushID(label)
} }
return ret; return ret;
} }
@ -6762,7 +6768,8 @@ bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags f
void ImGui::EndTabItem() void ImGui::EndTabItem()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.CurrentWindow->SkipItems) ImGuiWindow* window = g.CurrentWindow;
if (window->SkipItems)
return; return;
ImGuiTabBar* tab_bar = g.CurrentTabBar; ImGuiTabBar* tab_bar = g.CurrentTabBar;
@ -6774,7 +6781,7 @@ void ImGui::EndTabItem()
IM_ASSERT(tab_bar->LastTabItemIdx >= 0); IM_ASSERT(tab_bar->LastTabItemIdx >= 0);
ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx]; ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx];
if (!(tab->Flags & ImGuiTabItemFlags_NoPushId)) if (!(tab->Flags & ImGuiTabItemFlags_NoPushId))
g.CurrentWindow->IDStack.pop_back(); window->IDStack.pop_back();
} }
bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags, ImGuiWindow* docked_window) bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags, ImGuiWindow* docked_window)