1
0
mirror of https://github.com/ocornut/imgui.git synced 2024-12-01 02:37:24 +01:00

Merge branch 'master' into docking

# Conflicts:
#	backends/imgui_impl_glfw.cpp
#	backends/imgui_impl_osx.mm
#	backends/imgui_impl_sdl.cpp
#	backends/imgui_impl_win32.cpp
#	imgui.cpp
#	imgui.h
#	imgui_internal.h
#	imgui_widgets.cpp
This commit is contained in:
ocornut 2023-02-01 22:18:57 +01:00
commit 887abe9578
30 changed files with 676 additions and 180 deletions

View File

@ -21,6 +21,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)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2023-02-01: Inputs: flipping both wheel axises when running on Emscripten's GLFW emulation. (#6096)
// 2023-01-18: Handle unsupported glfwGetVideoMode() call on e.g. Emscripten. // 2023-01-18: Handle unsupported glfwGetVideoMode() call on e.g. Emscripten.
// 2023-01-04: Inputs: Fixed mods state on Linux when using Alt-GR text input (e.g. German keyboard layout), could lead to broken text input. Revert a 2022/01/17 change were we resumed using mods provided by GLFW, turns out they were faulty. // 2023-01-04: Inputs: Fixed mods state on Linux when using Alt-GR text input (e.g. German keyboard layout), could lead to broken text input. Revert a 2022/01/17 change were we resumed using mods provided by GLFW, turns out they were faulty.
// 2022-11-22: Perform a dummy glfwGetError() read to cancel missing names with glfwGetKeyName(). (#5908) // 2022-11-22: Perform a dummy glfwGetError() read to cancel missing names with glfwGetKeyName(). (#5908)
@ -318,6 +319,13 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo
if (bd->PrevUserCallbackScroll != nullptr && window == bd->Window) if (bd->PrevUserCallbackScroll != nullptr && window == bd->Window)
bd->PrevUserCallbackScroll(window, xoffset, yoffset); bd->PrevUserCallbackScroll(window, xoffset, yoffset);
#if defined(__EMSCRIPTEN__)
// Emscripten's GLFW emulation reports grossly mis-scaled and flipped scroll events.
// The scale is still currently incorrect, see #4019 #6096 for details.
xoffset /= -120.0f;
yoffset /= -120.0f;
#endif
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
io.AddMouseWheelEvent((float)xoffset, (float)yoffset); io.AddMouseWheelEvent((float)xoffset, (float)yoffset);
} }

View File

@ -9,6 +9,7 @@
// [X] Platform: Partial keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLUT values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: Partial keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLUT values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// 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 horizontal mouse wheel support.
// [ ] Platform: Missing mouse cursor shape/visibility support. // [ ] 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

@ -9,6 +9,7 @@
// [X] Platform: Partial keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLUT values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: Partial keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLUT values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// 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 horizontal mouse wheel support.
// [ ] Platform: Missing mouse cursor shape/visibility support. // [ ] 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

@ -26,6 +26,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)
// 2023-XX-XX: Added support for multiple windows via the ImGuiPlatformIO interface. // 2023-XX-XX: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2023-02-01: Fixed scroll wheel scaling for devices emitting events with hasPreciseScrollingDeltas==false (e.g. non-Apple mices).
// 2022-11-02: Fixed mouse coordinates before clicking the host window. // 2022-11-02: Fixed mouse coordinates before clicking the host window.
// 2022-10-06: Fixed mouse inputs on flipped views. // 2022-10-06: Fixed mouse inputs on flipped views.
// 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported). // 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
@ -692,18 +693,18 @@ static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
wheel_dy = [event scrollingDeltaY]; wheel_dy = [event scrollingDeltaY];
if ([event hasPreciseScrollingDeltas]) if ([event hasPreciseScrollingDeltas])
{ {
wheel_dx *= 0.1; wheel_dx *= 0.01;
wheel_dy *= 0.1; wheel_dy *= 0.01;
} }
} }
else else
#endif // MAC_OS_X_VERSION_MAX_ALLOWED #endif // MAC_OS_X_VERSION_MAX_ALLOWED
{ {
wheel_dx = [event deltaX]; wheel_dx = [event deltaX] * 0.1;
wheel_dy = [event deltaY]; wheel_dy = [event deltaY] * 0.1;
} }
if (wheel_dx != 0.0 || wheel_dy != 0.0) if (wheel_dx != 0.0 || wheel_dy != 0.0)
io.AddMouseWheelEvent((float)wheel_dx * 0.1f, (float)wheel_dy * 0.1f); io.AddMouseWheelEvent((float)wheel_dx, (float)wheel_dy);
return io.WantCaptureMouse; return io.WantCaptureMouse;
} }

View File

@ -21,6 +21,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)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2023-02-01: Flipping SDL_MOUSEWHEEL 'wheel.x' value to match other backends and offer consistent horizontal scrolling direction. (#4019, #6096, #1463)
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2022-09-26: Inputs: Disable SDL 2.0.22 new "auto capture" (SDL_HINT_MOUSE_AUTO_CAPTURE) which prevents drag and drop across windows for multi-viewport support + don't capture when drag and dropping. (#5710) // 2022-09-26: Inputs: Disable SDL 2.0.22 new "auto capture" (SDL_HINT_MOUSE_AUTO_CAPTURE) which prevents drag and drop across windows for multi-viewport support + don't capture when drag and dropping. (#5710)
// 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported). // 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
@ -287,7 +288,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
} }
case SDL_MOUSEWHEEL: case SDL_MOUSEWHEEL:
{ {
float wheel_x = (event->wheel.x > 0) ? 1.0f : (event->wheel.x < 0) ? -1.0f : 0.0f; float wheel_x = (event->wheel.x < 0) ? 1.0f : (event->wheel.x > 0) ? -1.0f : 0.0f; // About the clamping and flipped axis: see #4019
float wheel_y = (event->wheel.y > 0) ? 1.0f : (event->wheel.y < 0) ? -1.0f : 0.0f; float wheel_y = (event->wheel.y > 0) ? 1.0f : (event->wheel.y < 0) ? -1.0f : 0.0f;
io.AddMouseWheelEvent(wheel_x, wheel_y); io.AddMouseWheelEvent(wheel_x, wheel_y);
return true; return true;

View File

@ -13,6 +13,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)
// 2023-01-25: Revert automatic pipeline layout generation (see https://github.com/gpuweb/gpuweb/issues/2470)
// 2022-11-24: Fixed validation error with default depth buffer settings. // 2022-11-24: Fixed validation error with default depth buffer settings.
// 2022-11-10: Fixed rendering when a depth buffer is enabled. Added 'WGPUTextureFormat depth_format' parameter to ImGui_ImplWGPU_Init(). // 2022-11-10: Fixed rendering when a depth buffer is enabled. Added 'WGPUTextureFormat depth_format' parameter to ImGui_ImplWGPU_Init().
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
@ -554,7 +555,38 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
graphics_pipeline_desc.multisample.count = 1; graphics_pipeline_desc.multisample.count = 1;
graphics_pipeline_desc.multisample.mask = UINT_MAX; graphics_pipeline_desc.multisample.mask = UINT_MAX;
graphics_pipeline_desc.multisample.alphaToCoverageEnabled = false; graphics_pipeline_desc.multisample.alphaToCoverageEnabled = false;
graphics_pipeline_desc.layout = nullptr; // Use automatic layout generation
// Bind group layouts
WGPUBindGroupLayoutEntry common_bg_layout_entries[2] = {};
common_bg_layout_entries[0].binding = 0;
common_bg_layout_entries[0].visibility = WGPUShaderStage_Vertex;
common_bg_layout_entries[0].buffer.type = WGPUBufferBindingType_Uniform;
common_bg_layout_entries[1].binding = 1;
common_bg_layout_entries[1].visibility = WGPUShaderStage_Fragment;
common_bg_layout_entries[1].sampler.type = WGPUSamplerBindingType_Filtering;
WGPUBindGroupLayoutEntry image_bg_layout_entries[1] = {};
image_bg_layout_entries[0].binding = 0;
image_bg_layout_entries[0].visibility = WGPUShaderStage_Fragment;
image_bg_layout_entries[0].texture.sampleType = WGPUTextureSampleType_Float;
image_bg_layout_entries[0].texture.viewDimension = WGPUTextureViewDimension_2D;
WGPUBindGroupLayoutDescriptor common_bg_layout_desc = {};
common_bg_layout_desc.entryCount = 2;
common_bg_layout_desc.entries = common_bg_layout_entries;
WGPUBindGroupLayoutDescriptor image_bg_layout_desc = {};
image_bg_layout_desc.entryCount = 1;
image_bg_layout_desc.entries = image_bg_layout_entries;
WGPUBindGroupLayout bg_layouts[2];
bg_layouts[0] = wgpuDeviceCreateBindGroupLayout(g_wgpuDevice, &common_bg_layout_desc);
bg_layouts[1] = wgpuDeviceCreateBindGroupLayout(g_wgpuDevice, &image_bg_layout_desc);
WGPUPipelineLayoutDescriptor layout_desc = {};
layout_desc.bindGroupLayoutCount = 2;
layout_desc.bindGroupLayouts = bg_layouts;
graphics_pipeline_desc.layout = wgpuDeviceCreatePipelineLayout(g_wgpuDevice, &layout_desc);
// Create the vertex shader // Create the vertex shader
WGPUProgrammableStageDescriptor vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModule(__glsl_shader_vert_spv, sizeof(__glsl_shader_vert_spv) / sizeof(uint32_t)); WGPUProgrammableStageDescriptor vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModule(__glsl_shader_vert_spv, sizeof(__glsl_shader_vert_spv) / sizeof(uint32_t));
@ -620,10 +652,6 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
ImGui_ImplWGPU_CreateUniformBuffer(); ImGui_ImplWGPU_CreateUniformBuffer();
// Create resource bind group // Create resource bind group
WGPUBindGroupLayout bg_layouts[2];
bg_layouts[0] = wgpuRenderPipelineGetBindGroupLayout(g_pipelineState, 0);
bg_layouts[1] = wgpuRenderPipelineGetBindGroupLayout(g_pipelineState, 1);
WGPUBindGroupEntry common_bg_entries[] = WGPUBindGroupEntry common_bg_entries[] =
{ {
{ nullptr, 0, g_resources.Uniforms, 0, sizeof(Uniforms), 0, 0 }, { nullptr, 0, g_resources.Uniforms, 0, sizeof(Uniforms), 0, 0 },

View File

@ -36,6 +36,7 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
// 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)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2023-02-02: Inputs: Flipping WM_MOUSEHWHEEL (horizontal mouse-wheel) value to match other backends and offer consistent horizontal scrolling direction. (#4019, #6096, #1463)
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2022-09-28: Inputs: Convert WM_CHAR values with MultiByteToWideChar() when window class was registered as MBCS (not Unicode). // 2022-09-28: Inputs: Convert WM_CHAR values with MultiByteToWideChar() when window class was registered as MBCS (not Unicode).
// 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported). // 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
@ -643,7 +644,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
io.AddMouseWheelEvent(0.0f, (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA); io.AddMouseWheelEvent(0.0f, (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA);
return 0; return 0;
case WM_MOUSEHWHEEL: case WM_MOUSEHWHEEL:
io.AddMouseWheelEvent((float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA, 0.0f); io.AddMouseWheelEvent(-(float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA, 0.0f);
return 0; return 0;
case WM_KEYDOWN: case WM_KEYDOWN:
case WM_KEYUP: case WM_KEYUP:

View File

@ -102,18 +102,69 @@ Other changes:
VERSION 1.89.3 (In Progress) VERSION 1.89.3 (In Progress)
----------------------------------------------------------------------- -----------------------------------------------------------------------
Breaking changes:
- Inputs, Scrolling: Made horizontal scroll wheel and horizontal scroll direction consistent
accross backends/os. (#4019, #6096, #1463) [@PathogenDavid, @ocornut, @rokups]
- Clarified that 'wheel_y > 0.0f' scrolls Up, 'wheel_y > 0.0f' scrolls Down.
- Clarified that 'wheel_x > 0.0f' scrolls Left, 'wheel_x > 0.0f' scrolls Right.
- Backends: Win32: flipping WM_MOUSEHWHEEL value to match other backends and
offer consistent horizontal scrolling direction. (#4019)
- Backends: SDL: flipping SDL_MOUSEWHEEL 'wheel.x' value to match other backends and
offer consistent horizontal scrolling direction. (#4019)
- Backends: GLFW+Emscripten: flipping both wheels axises + scaling magnitude down when
running on Emscripten's GLFW emulation. (#6096) [@topolarity]
- Shift+WheelY support on non-OSX machines was already correct. (#2424, #1463)
(whereaas on OSX machines Shift+WheelY turns into WheelX at the OS level).
- If you use a custom-backend, you should verify that:
- Wheel up (*) emit wheel_y > 0.0f values and scrolls up.
- Wheel down (*) emit wheel_y < 0.0f values and scrolls down.
- Wheel left (*) or mod+wheel up emit wheel_x > 0.0f values and scroll Left.
- Wheel right (*) or mod+wheel down emits wheel_x < 0.0f values and scroll Right.
- (*) both axises flipped on OSX for mouse and touchpad when 'Natural Scrolling' is on.
- (*) both axises flipped On Windows for touchpad only when 'Settings->Touchpad->Down motion scrolls up' is set.
- You can use 'Demo->Tools->Debug Log->IO" to visualize values submitted to Dear ImGui.
- Known issues remaining with Emscripten:
- The magnitude of wheeling values on Emscripten setups is still mostly wrong. (#6096)
- When running the Emscripten app on a Mac with a mouse, SHIFT+WheelY doesn't turn into WheelX.
This is because we don't know that we are running on Mac and apply our own Shift+swapping
on top of OSX' own swapping, so wheel axises are swapped twice. Emscripten apps may need
to find a way to detect this and set io.ConfigMacOSXBehaviors manually (if you know a way
let us know!), or offer the "OSX-style behavior" option to their user.
All changes: All changes:
- Window: Avoid rendering shapes for hidden resize grips.
- Tables: Raised max Columns count from 64 to 512. (#6094, #5305, #4876, #3572) - Tables: Raised max Columns count from 64 to 512. (#6094, #5305, #4876, #3572)
The previous limit was due to using 64-bit integers but we moved to bits-array The previous limit was due to using 64-bit integers but we moved to bits-array
and tweaked the system enough to ensure no performance loss. and tweaked the system enough to ensure no performance loss.
- Text: Fixed layouting of wrapped-text block skipping successive empty lines, - Text: Fixed layouting of wrapped-text block skipping successive empty lines,
regression from the fix in 1.89.2. (#5720, #5919) regression from the fix in 1.89.2. (#5720, #5919)
- Text: Fix clipping of single-character "..." ellipsis (U+2026 or U+0085) when font - Text: Fixed clipping of single-character "..." ellipsis (U+2026 or U+0085) when font
is scaled. Scaling wasn't taken into account, leading to ellipsis character straying is scaled. Scaling wasn't taken into account, leading to ellipsis character straying
slightly out of its expected boundaries. (#2775) slightly out of its expected boundaries. (#2775)
- Text: Tweaked rendering of three-dots "..." ellipsis variant. (#2775, #4269) - Text: Tweaked rendering of three-dots "..." ellipsis variant. (#2775, #4269)
- InputText: Added support for Ctrl+Delete to delete up to end-of-word. (#6067) [@ajweeks]
(Not adding Super+Delete to delete to up to end-of-line on OSX, as OSX doesn't have it)
- InputText: On OSX, inhibit usage of Alt key to toggle menu when active (used for work skip).
- Menus: Fixed layout of MenuItem()/BeginMenu() when label contains a '\n'. (#6116) [@imkcy9]
- PlotHistogram, PlotLines: Passing negative sizes honor alignment like other widgets. - PlotHistogram, PlotLines: Passing negative sizes honor alignment like other widgets.
- Combo: Allow SetNextWindowSize() to alter combo popup size. (#6130)
- ImDrawList: Added missing early-out in AddPolyline() and AddConvexPolyFilled() when
color alpha is zero.
- Misc: Most text functions treat "%s" as a shortcut to no-formatting. (#3466)
- Misc: Tolerate zero delta-time under Emscripten as backends are imprecise in their
values for io.DeltaTime, and browser features such as "privacy.resistFingerprinting=true"
can exacerbate that. (#6114, #3644)
- Backends: OSX: Fixed scroll/wheel scaling for devices emitting events with
hasPreciseScrollingDeltas==false (e.g. non-Apple mices).
- Backend: WebGPU: Fix building for latest WebGPU specs (remove implicit layout generation).
(#6117, #4116, #3632) [@tonygrue, @bfierz]
- Examples: Win32: Fixed examples using RegisterClassW() since 1.89 to also call
DefWindowProcW() instead of DefWindowProc() so that title text are correctly converted
when application is compiled without /DUNICODE. (#5725, #5961, #5975) [@markreidvfx]
- Examples: SDL+SDL_Renderer: Added call to SDL_RenderSetScale() to display is correct on a
Retina display (albeit lower-res as our other unmodified examples). (#6121, #6065, #5931).
Docking+Viewports Branch: Docking+Viewports Branch:

View File

@ -644,7 +644,7 @@ You may take a look at:
- [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) - [Quotes](https://github.com/ocornut/imgui/wiki/Quotes)
- [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui)
- [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors) - [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors)
- [Gallery](https://github.com/ocornut/imgui/issues/5243) - [Gallery](https://github.com/ocornut/imgui/issues/5886)
##### [Return to Index](#index) ##### [Return to Index](#index)
@ -690,7 +690,7 @@ There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/ci
- Individuals: you can support continued maintenance and development via PayPal donations. See [README](https://github.com/ocornut/imgui/blob/master/docs/README.md). - Individuals: you can support continued maintenance and development via PayPal donations. See [README](https://github.com/ocornut/imgui/blob/master/docs/README.md).
- If you are experienced with Dear ImGui and C++, look at [GitHub Issues](https://github.com/ocornut/imgui/issues), [GitHub Discussions](https://github.com/ocornut/imgui/discussions), the [Wiki](https://github.com/ocornut/imgui/wiki), read [docs/TODO.txt](https://github.com/ocornut/imgui/blob/master/docs/TODO.txt), and see how you want to help and can help! - If you are experienced with Dear ImGui and C++, look at [GitHub Issues](https://github.com/ocornut/imgui/issues), [GitHub Discussions](https://github.com/ocornut/imgui/discussions), the [Wiki](https://github.com/ocornut/imgui/wiki), read [docs/TODO.txt](https://github.com/ocornut/imgui/blob/master/docs/TODO.txt), and see how you want to help and can help!
- Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere, etc. - Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere, etc.
You may post screenshots or links in the [gallery threads](https://github.com/ocornut/imgui/issues/5243). Visuals are ideal as they inspire other programmers. Disclosing your use of Dear ImGui helps the library grow credibility, and helps other teams and programmers with taking decisions. You may post screenshots or links in the [gallery threads](https://github.com/ocornut/imgui/issues/5886). Visuals are ideal as they inspire other programmers. Disclosing your use of Dear ImGui helps the library grow credibility, and helps other teams and programmers with taking decisions.
- If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues or sometimes incomplete PR. - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues or sometimes incomplete PR.
##### [Return to Index](#index) ##### [Return to Index](#index)

View File

@ -135,7 +135,7 @@ Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas.
### Gallery ### Gallery
For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/5243)! For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/5886)!
For a list of third-party widgets and extensions, check out the [Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page. For a list of third-party widgets and extensions, check out the [Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page.
@ -166,7 +166,7 @@ We occasionally tag [Releases](https://github.com/ocornut/imgui/releases) (with
**Who uses Dear ImGui?** **Who uses Dear ImGui?**
See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes), [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors), and [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for an idea of who is using Dear ImGui. Please add your game/software if you can! Also, see the [Gallery Threads](https://github.com/ocornut/imgui/issues/5243)! See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes), [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors), and [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for an idea of who is using Dear ImGui. Please add your game/software if you can! Also, see the [Gallery Threads](https://github.com/ocornut/imgui/issues/5886)!
How to help How to help
----------- -----------

View File

@ -0,0 +1,91 @@
#
# Makefile to use with GLFW+emscripten
# See https://emscripten.org/docs/getting_started/downloads.html
# for installation instructions.
#
# This Makefile assumes you have loaded emscripten's environment.
# (On Windows, you may need to execute emsdk_env.bat or encmdprompt.bat ahead)
#
# Running `make` will produce three files:
# - web/index.html
# - web/index.js
# - web/index.wasm
#
# All three are needed to run the demo.
CC = emcc
CXX = em++
WEB_DIR = web
EXE = $(WEB_DIR)/index.html
IMGUI_DIR = ../..
SOURCES = main.cpp
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
CPPFLAGS =
LDFLAGS =
EMS =
##---------------------------------------------------------------------
## EMSCRIPTEN OPTIONS
##---------------------------------------------------------------------
# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
EMS += -s USE_GLFW=3
EMS += -s DISABLE_EXCEPTION_CATCHING=1
LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
# Uncomment next line to fix possible rendering bugs with Emscripten version older then 1.39.0 (https://github.com/ocornut/imgui/issues/2877)
#EMS += -s BINARYEN_TRAP_MODE=clamp
#EMS += -s SAFE_HEAP=1 ## Adds overhead
# Emscripten allows preloading a file or folder to be accessible at runtime.
# The Makefile for this example project suggests embedding the misc/fonts/ folder into our application, it will then be accessible as "/fonts"
# See documentation for more details: https://emscripten.org/docs/porting/files/packaging_files.html
# (Default value is 0. Set to 1 to enable file-system and include the misc/fonts/ folder as part of the build.)
USE_FILE_SYSTEM ?= 0
ifeq ($(USE_FILE_SYSTEM), 0)
LDFLAGS += -s NO_FILESYSTEM=1
CPPFLAGS += -DIMGUI_DISABLE_FILE_FUNCTIONS
endif
ifeq ($(USE_FILE_SYSTEM), 1)
LDFLAGS += --no-heap-copy --preload-file ../../misc/fonts@/fonts
endif
##---------------------------------------------------------------------
## FINAL BUILD FLAGS
##---------------------------------------------------------------------
CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
#CPPFLAGS += -g
CPPFLAGS += -Wall -Wformat -Os $(EMS)
LDFLAGS += --shell-file shell_minimal.html $(EMS)
##---------------------------------------------------------------------
## BUILD RULES
##---------------------------------------------------------------------
%.o:%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/backends/%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
all: $(EXE)
@echo Build complete for $(EXE)
$(WEB_DIR):
mkdir $@
serve: all
python3 -m http.server -d $(WEB_DIR)
$(EXE): $(OBJS) $(WEB_DIR)
$(CXX) -o $@ $(OBJS) $(LDFLAGS)
clean:
rm -rf $(OBJS) $(WEB_DIR)

View File

@ -0,0 +1,167 @@
// Dear ImGui: standalone example application for Emscripten, using GLFW + OpenGL3
// (Emscripten is a C++-to-javascript compiler, used to publish executables for the web. See https://emscripten.org/)
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// This is mostly the same code as the GLFW + OpenGL3 example, simply with the modifications needed to run on Emscripten.
// It is possible to combine both code into a single source file that will compile properly on Desktop and using Emscripten.
// See https://github.com/ocornut/imgui/pull/2492 as an example on how to do just that.
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
#include <stdio.h>
#include <emscripten.h>
#define GL_SILENCE_DEPRECATION
#if defined(IMGUI_IMPL_OPENGL_ES2)
#include <GLES2/gl2.h>
#endif
#include <GLFW/glfw3.h> // Will drag system OpenGL headers
// Emscripten requires to have full control over the main loop. We're going to store our GLFW book-keeping variables globally.
// Having a single function that acts as a loop prevents us to store state in the stack of said function. So we need some location for this.
GLFWwindow* g_Window = NULL;
static void glfw_error_callback(int error, const char* description)
{
fprintf(stderr, "Glfw Error %d: %s\n", error, description);
}
// For clarity, our main loop code is declared at the end.
static void main_loop(void*);
int main(int, char**)
{
// Setup window
glfwSetErrorCallback(glfw_error_callback);
if (!glfwInit())
return 1;
// For the browser using Emscripten, we are going to use WebGL1 with GL ES2. See the Makefile. for requirement details.
// It is very likely the generated file won't work in many browsers. Firefox is the only sure bet, but I have successfully
// run this code on Chrome for Android for example.
const char* glsl_version = "#version 100";
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
// Create window with graphics context
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+Emscripten example", NULL, NULL);
if (window == NULL)
return 1;
glfwMakeContextCurrent(window);
glfwSwapInterval(1); // Enable vsync
g_Window = window;
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
//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.
// You may manually call LoadIniSettingsFromMemory() to load settings from your own storage.
io.IniFilename = NULL;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
// Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init(glsl_version);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - Read 'docs/FONTS.md' for more instructions and details.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
// - Emscripten allows preloading a file or folder to be accessible at runtime. See Makefile for details.
//io.Fonts->AddFontDefault();
#ifndef IMGUI_DISABLE_FILE_FUNCTIONS
//io.Fonts->AddFontFromFileTTF("fonts/segoeui.ttf", 18.0f);
io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("fonts/ProggyTiny.ttf", 10.0f);
//ImFont* font = io.Fonts->AddFontFromFileTTF("fonts/ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
#endif
// This function call won't return, and will engage in an infinite loop, processing events from the browser, and dispatching them.
emscripten_set_main_loop_arg(main_loop, NULL, 0, true);
}
static void main_loop(void* arg)
{
IM_UNUSED(arg); // We can pass this argument as the second parameter of emscripten_set_main_loop_arg(), but we don't use that.
// Our state (make them static = more or less global) as a convenience to keep the example terse.
static bool show_demo_window = true;
static bool show_another_window = false;
static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Poll and handle events (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
glfwPollEvents();
// Start the Dear ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
}
// 3. Show another simple window.
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
// Rendering
ImGui::Render();
int display_w, display_h;
glfwGetFramebufferSize(g_Window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(g_Window);
}

View File

@ -0,0 +1,64 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
<title>Dear ImGui GLFW+Emscripten example</title>
<style>
body { margin: 0; background-color: black }
.emscripten {
position: absolute;
top: 0px;
left: 0px;
margin: 0px;
border: 0;
width: 100%;
height: 100%;
overflow: hidden;
display: block;
image-rendering: optimizeSpeed;
image-rendering: -moz-crisp-edges;
image-rendering: -o-crisp-edges;
image-rendering: -webkit-optimize-contrast;
image-rendering: optimize-contrast;
image-rendering: crisp-edges;
image-rendering: pixelated;
-ms-interpolation-mode: nearest-neighbor;
}
</style>
</head>
<body>
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<script type='text/javascript'>
var Module = {
preRun: [],
postRun: [],
print: (function() {
return function(text) {
text = Array.prototype.slice.call(arguments).join(' ');
console.log(text);
};
})(),
printErr: function(text) {
text = Array.prototype.slice.call(arguments).join(' ');
console.error(text);
},
canvas: (function() {
var canvas = document.getElementById('canvas');
//canvas.addEventListener("webglcontextlost", function(e) { alert('FIXME: WebGL context lost, please reload the page'); e.preventDefault(); }, false);
return canvas;
})(),
setStatus: function(text) {
console.log("status: " + text);
},
monitorRunDependencies: function(left) {
// no run dependencies to log
}
};
window.onerror = function() {
console.log("onerror: " + event);
};
</script>
{{{ SCRIPT }}}
</body>
</html>

View File

@ -1,5 +1,5 @@
# #
# Makefile to use with emscripten # Makefile to use with SDL+emscripten
# See https://emscripten.org/docs/getting_started/downloads.html # See https://emscripten.org/docs/getting_started/downloads.html
# for installation instructions. # for installation instructions.
# #

View File

@ -49,7 +49,7 @@ int main(int, char**)
SDL_DisplayMode current; SDL_DisplayMode current;
SDL_GetCurrentDisplayMode(0, &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);
g_Window = SDL_CreateWindow("Dear ImGui Emscripten example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); g_Window = SDL_CreateWindow("Dear ImGui SDL+Emscripten example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
g_GLContext = SDL_GL_CreateContext(g_Window); g_GLContext = SDL_GL_CreateContext(g_Window);
if (!g_GLContext) if (!g_GLContext)
{ {

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
<title>Dear ImGui Emscripten example</title> <title>Dear ImGui SDL+Emscripten example</title>
<style> <style>
body { margin: 0; background-color: black } body { margin: 0; background-color: black }
.emscripten { .emscripten {

View File

@ -143,6 +143,7 @@ int main(int, char**)
// Rendering // Rendering
ImGui::Render(); ImGui::Render();
SDL_RenderSetScale(renderer, io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
SDL_SetRenderDrawColor(renderer, (Uint8)(clear_color.x * 255), (Uint8)(clear_color.y * 255), (Uint8)(clear_color.z * 255), (Uint8)(clear_color.w * 255)); SDL_SetRenderDrawColor(renderer, (Uint8)(clear_color.x * 255), (Uint8)(clear_color.y * 255), (Uint8)(clear_color.z * 255), (Uint8)(clear_color.w * 255));
SDL_RenderClear(renderer); SDL_RenderClear(renderer);
ImGui_ImplSDLRenderer_RenderDrawData(ImGui::GetDrawData()); ImGui_ImplSDLRenderer_RenderDrawData(ImGui::GetDrawData());

View File

@ -262,5 +262,5 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
::PostQuitMessage(0); ::PostQuitMessage(0);
return 0; return 0;
} }
return ::DefWindowProc(hWnd, msg, wParam, lParam); return ::DefWindowProcW(hWnd, msg, wParam, lParam);
} }

View File

@ -284,5 +284,5 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
} }
break; break;
} }
return ::DefWindowProc(hWnd, msg, wParam, lParam); return ::DefWindowProcW(hWnd, msg, wParam, lParam);
} }

View File

@ -481,5 +481,5 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
::PostQuitMessage(0); ::PostQuitMessage(0);
return 0; return 0;
} }
return ::DefWindowProc(hWnd, msg, wParam, lParam); return ::DefWindowProcW(hWnd, msg, wParam, lParam);
} }

View File

@ -267,5 +267,5 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
} }
break; break;
} }
return ::DefWindowProc(hWnd, msg, wParam, lParam); return ::DefWindowProcW(hWnd, msg, wParam, lParam);
} }

View File

@ -11,7 +11,7 @@
// - FAQ http://dearimgui.org/faq // - FAQ http://dearimgui.org/faq
// - Homepage & latest https://github.com/ocornut/imgui // - Homepage & latest https://github.com/ocornut/imgui
// - Releases & changelog https://github.com/ocornut/imgui/releases // - Releases & changelog https://github.com/ocornut/imgui/releases
// - Gallery https://github.com/ocornut/imgui/issues/5243 (please post your screenshots/video there!) // - Gallery https://github.com/ocornut/imgui/issues/5886 (please post your screenshots/video there!)
// - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there) // - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there)
// - Glossary https://github.com/ocornut/imgui/wiki/Glossary // - Glossary https://github.com/ocornut/imgui/wiki/Glossary
// - Issues & support https://github.com/ocornut/imgui/issues // - Issues & support https://github.com/ocornut/imgui/issues
@ -1503,7 +1503,7 @@ void ImGuiIO::AddMouseButtonEvent(int mouse_button, bool down)
g.InputEventsQueue.push_back(e); g.InputEventsQueue.push_back(e);
} }
// Queue a mouse wheel event (most mouse/API will only have a Y component) // Queue a mouse wheel event (some mouse/API may only have a Y component)
void ImGuiIO::AddMouseWheelEvent(float wheel_x, float wheel_y) void ImGuiIO::AddMouseWheelEvent(float wheel_x, float wheel_y)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -1862,18 +1862,36 @@ void ImFormatStringToTempBuffer(const char** out_buf, const char** out_buf_end,
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
int buf_len = ImFormatStringV(g.TempBuffer.Data, g.TempBuffer.Size, fmt, args); if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0)
*out_buf = g.TempBuffer.Data; {
if (out_buf_end) { *out_buf_end = g.TempBuffer.Data + buf_len; } const char* buf = va_arg(args, const char*); // Skip formatting when using "%s"
*out_buf = buf;
if (out_buf_end) { *out_buf_end = buf + strlen(buf); }
}
else
{
int buf_len = ImFormatStringV(g.TempBuffer.Data, g.TempBuffer.Size, fmt, args);
*out_buf = g.TempBuffer.Data;
if (out_buf_end) { *out_buf_end = g.TempBuffer.Data + buf_len; }
}
va_end(args); va_end(args);
} }
void ImFormatStringToTempBufferV(const char** out_buf, const char** out_buf_end, const char* fmt, va_list args) void ImFormatStringToTempBufferV(const char** out_buf, const char** out_buf_end, const char* fmt, va_list args)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
int buf_len = ImFormatStringV(g.TempBuffer.Data, g.TempBuffer.Size, fmt, args); if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0)
*out_buf = g.TempBuffer.Data; {
if (out_buf_end) { *out_buf_end = g.TempBuffer.Data + buf_len; } const char* buf = va_arg(args, const char*); // Skip formatting when using "%s"
*out_buf = buf;
if (out_buf_end) { *out_buf_end = buf + strlen(buf); }
}
else
{
int buf_len = ImFormatStringV(g.TempBuffer.Data, g.TempBuffer.Size, fmt, args);
*out_buf = g.TempBuffer.Data;
if (out_buf_end) { *out_buf_end = g.TempBuffer.Data + buf_len; }
}
} }
// CRC32 needs a 1KB lookup table (not cache friendly) // CRC32 needs a 1KB lookup table (not cache friendly)
@ -1960,7 +1978,7 @@ ImFileHandle ImFileOpen(const char* filename, const char* mode)
// Previously we used ImTextCountCharsFromUtf8/ImTextStrFromUtf8 here but we now need to support ImWchar16 and ImWchar32! // Previously we used ImTextCountCharsFromUtf8/ImTextStrFromUtf8 here but we now need to support ImWchar16 and ImWchar32!
const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0); const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0);
const int mode_wsize = ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0); const int mode_wsize = ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0);
ImVector<ImWchar> buf; ImVector<wchar_t> buf;
buf.resize(filename_wsize + mode_wsize); buf.resize(filename_wsize + mode_wsize);
::MultiByteToWideChar(CP_UTF8, 0, filename, -1, (wchar_t*)&buf[0], filename_wsize); ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, (wchar_t*)&buf[0], filename_wsize);
::MultiByteToWideChar(CP_UTF8, 0, mode, -1, (wchar_t*)&buf[filename_wsize], mode_wsize); ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, (wchar_t*)&buf[filename_wsize], mode_wsize);
@ -6173,12 +6191,15 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
{ {
for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++) for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
{ {
const ImU32 col = resize_grip_col[resize_grip_n];
if ((col & IM_COL32_A_MASK) == 0)
continue;
const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n]; const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n];
const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPosN); const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPosN);
window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, resize_grip_draw_size) : ImVec2(resize_grip_draw_size, window_border_size))); window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, resize_grip_draw_size) : ImVec2(resize_grip_draw_size, window_border_size)));
window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(resize_grip_draw_size, window_border_size) : ImVec2(window_border_size, resize_grip_draw_size))); window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(resize_grip_draw_size, window_border_size) : ImVec2(window_border_size, resize_grip_draw_size)));
window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + window_border_size), corner.y + grip.InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.AngleMin12, grip.AngleMax12); window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + window_border_size), corner.y + grip.InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.AngleMin12, grip.AngleMax12);
window->DrawList->PathFillConvex(resize_grip_col[resize_grip_n]); window->DrawList->PathFillConvex(col);
} }
} }
@ -9075,7 +9096,8 @@ void ImGui::UpdateMouseWheel()
// Mouse wheel scrolling // Mouse wheel scrolling
// As a standard behavior holding SHIFT while using Vertical Mouse Wheel triggers Horizontal scroll instead // As a standard behavior holding SHIFT while using Vertical Mouse Wheel triggers Horizontal scroll instead
// (we avoid doing it on OSX as it the OS input layer handles this already) // - We avoid doing it on OSX as it the OS input layer handles this already.
// - However this means when running on OSX over Emcripten, Shift+WheelY will incur two swappings (1 in OS, 1 here), cancelling the feature.
const bool swap_axis = g.IO.KeyShift && !g.IO.ConfigMacOSXBehaviors; const bool swap_axis = g.IO.KeyShift && !g.IO.ConfigMacOSXBehaviors;
if (swap_axis) if (swap_axis)
{ {
@ -9462,6 +9484,13 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
// #define IM_ASSERT(EXPR) do { if (SomeCode(EXPR)) SomeMoreCode(); } while (0) // Correct! // #define IM_ASSERT(EXPR) do { if (SomeCode(EXPR)) SomeMoreCode(); } while (0) // Correct!
if (true) IM_ASSERT(1); else IM_ASSERT(0); if (true) IM_ASSERT(1); else IM_ASSERT(0);
// Emscripten backends are often imprecise in their submission of DeltaTime. (#6114, #3644)
// Ideally the Emscripten app/backend should aim to fix or smooth this value and avoid feeding zero, but we tolerate it.
#ifdef __EMSCRIPTEN__
if (g.IO.DeltaTime <= 0.0f && g.FrameCount > 0)
g.IO.DeltaTime = 0.00001f;
#endif
// Check user data // Check user data
// (We pass an error message in the assert expression to make it visible to programmers who are not using a debugger, as most assert handlers display their argument) // (We pass an error message in the assert expression to make it visible to programmers who are not using a debugger, as most assert handlers display their argument)
IM_ASSERT(g.Initialized); IM_ASSERT(g.Initialized);
@ -15311,7 +15340,7 @@ int ImGui::DockNodeGetTabOrder(ImGuiWindow* window)
if (tab_bar == NULL) if (tab_bar == NULL)
return -1; return -1;
ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, window->TabId); ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, window->TabId);
return tab ? tab_bar->GetTabOrder(tab) : -1; return tab ? TabBarGetTabOrder(tab_bar, tab) : -1;
} }
static void DockNodeHideWindowDuringHostWindowCreation(ImGuiWindow* window) static void DockNodeHideWindowDuringHostWindowCreation(ImGuiWindow* window)
@ -16063,7 +16092,7 @@ static ImGuiID ImGui::DockNodeUpdateWindowMenu(ImGuiDockNode* node, ImGuiTabBar*
ImGuiTabItem* tab = &tab_bar->Tabs[tab_n]; ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
if (tab->Flags & ImGuiTabItemFlags_Button) if (tab->Flags & ImGuiTabItemFlags_Button)
continue; continue;
if (Selectable(tab_bar->GetTabName(tab), tab->ID == tab_bar->SelectedTabId)) if (Selectable(TabBarGetTabName(tab_bar, tab), tab->ID == tab_bar->SelectedTabId))
ret_tab_id = tab->ID; ret_tab_id = tab->ID;
SameLine(); SameLine();
Text(" "); Text(" ");
@ -18639,10 +18668,13 @@ void ImGui::ShowFontAtlas(ImFontAtlas* atlas)
DebugNodeFont(font); DebugNodeFont(font);
PopID(); PopID();
} }
if (TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight)) if (TreeNode("Font Atlas", "Font Atlas (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
{ {
ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); ImGuiContext& g = *GImGui;
ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f); ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig;
Checkbox("Tint with Text Color", &cfg->ShowAtlasTintedWithTextColor); // Using text color ensure visibility of core atlas data, but will alter custom colored icons
ImVec4 tint_col = cfg->ShowAtlasTintedWithTextColor ? GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
ImVec4 border_col = GetStyleColorVec4(ImGuiCol_Border);
Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), tint_col, border_col); Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), tint_col, border_col);
TreePop(); TreePop();
} }
@ -19606,7 +19638,7 @@ void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label)
{ {
ImGuiTabItem* tab = &tab_bar->Tabs[tab_n]; ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
p += ImFormatString(p, buf_end - p, "%s'%s'", p += ImFormatString(p, buf_end - p, "%s'%s'",
tab_n > 0 ? ", " : "", (tab->Window || tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "???"); tab_n > 0 ? ", " : "", (tab->Window || tab->NameOffset != -1) ? TabBarGetTabName(tab_bar, tab) : "???");
} }
p += ImFormatString(p, buf_end - p, (tab_bar->Tabs.Size > 3) ? " ... }" : " } "); p += ImFormatString(p, buf_end - p, (tab_bar->Tabs.Size > 3) ? " ... }" : " } ");
if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
@ -19623,12 +19655,12 @@ void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label)
{ {
for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++) for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
{ {
const ImGuiTabItem* tab = &tab_bar->Tabs[tab_n]; ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
PushID(tab); PushID(tab);
if (SmallButton("<")) { TabBarQueueReorder(tab_bar, tab, -1); } SameLine(0, 2); if (SmallButton("<")) { TabBarQueueReorder(tab_bar, tab, -1); } SameLine(0, 2);
if (SmallButton(">")) { TabBarQueueReorder(tab_bar, tab, +1); } SameLine(); if (SmallButton(">")) { TabBarQueueReorder(tab_bar, tab, +1); } SameLine();
Text("%02d%c Tab 0x%08X '%s' Offset: %.2f, Width: %.2f/%.2f", Text("%02d%c Tab 0x%08X '%s' Offset: %.2f, Width: %.2f/%.2f",
tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID, (tab->Window || tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "???", tab->Offset, tab->Width, tab->ContentWidth); tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID, (tab->Window || tab->NameOffset != -1) ? TabBarGetTabName(tab_bar, tab) : "???", tab->Offset, tab->Width, tab->ContentWidth);
PopID(); PopID();
} }
TreePop(); TreePop();

10
imgui.h
View File

@ -11,7 +11,7 @@
// - FAQ http://dearimgui.org/faq // - FAQ http://dearimgui.org/faq
// - Homepage & latest https://github.com/ocornut/imgui // - Homepage & latest https://github.com/ocornut/imgui
// - Releases & changelog https://github.com/ocornut/imgui/releases // - Releases & changelog https://github.com/ocornut/imgui/releases
// - Gallery https://github.com/ocornut/imgui/issues/5243 (please post your screenshots/video there!) // - Gallery https://github.com/ocornut/imgui/issues/5886 (please post your screenshots/video there!)
// - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there) // - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there)
// - Glossary https://github.com/ocornut/imgui/wiki/Glossary // - Glossary https://github.com/ocornut/imgui/wiki/Glossary
// - Issues & support https://github.com/ocornut/imgui/issues // - Issues & support https://github.com/ocornut/imgui/issues
@ -23,7 +23,7 @@
// Library Version // Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM > 12345') // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM > 12345')
#define IMGUI_VERSION "1.89.3 WIP" #define IMGUI_VERSION "1.89.3 WIP"
#define IMGUI_VERSION_NUM 18923 #define IMGUI_VERSION_NUM 18926
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch #define IMGUI_HAS_VIEWPORT // Viewport WIP branch
#define IMGUI_HAS_DOCK // Docking WIP branch #define IMGUI_HAS_DOCK // Docking WIP branch
@ -2055,7 +2055,7 @@ struct ImGuiIO
IMGUI_API void AddKeyAnalogEvent(ImGuiKey key, bool down, float v); // Queue a new key down/up event for analog values (e.g. ImGuiKey_Gamepad_ values). Dead-zones should be handled by the backend. IMGUI_API void AddKeyAnalogEvent(ImGuiKey key, bool down, float v); // Queue a new key down/up event for analog values (e.g. ImGuiKey_Gamepad_ values). Dead-zones should be handled by the backend.
IMGUI_API void AddMousePosEvent(float x, float y); // Queue a mouse position update. Use -FLT_MAX,-FLT_MAX to signify no mouse (e.g. app not focused and not hovered) IMGUI_API void AddMousePosEvent(float x, float y); // Queue a mouse position update. Use -FLT_MAX,-FLT_MAX to signify no mouse (e.g. app not focused and not hovered)
IMGUI_API void AddMouseButtonEvent(int button, bool down); // Queue a mouse button change IMGUI_API void AddMouseButtonEvent(int button, bool down); // Queue a mouse button change
IMGUI_API void AddMouseWheelEvent(float wh_x, float wh_y); // Queue a mouse wheel update IMGUI_API void AddMouseWheelEvent(float wheel_x, float wheel_y); // Queue a mouse wheel update. wheel_y<0: scroll down, wheel_y>0: scroll up, wheel_x<0: scroll right, wheel_x>0: scroll left.
IMGUI_API void AddMouseViewportEvent(ImGuiID id); // Queue a mouse hovered viewport. Requires backend to set ImGuiBackendFlags_HasMouseHoveredViewport to call this (for multi-viewport support). IMGUI_API void AddMouseViewportEvent(ImGuiID id); // Queue a mouse hovered viewport. Requires backend to set ImGuiBackendFlags_HasMouseHoveredViewport to call this (for multi-viewport support).
IMGUI_API void AddFocusEvent(bool focused); // Queue a gain/loss of focus for the application (generally based on OS/platform focus of your window) IMGUI_API void AddFocusEvent(bool focused); // Queue a gain/loss of focus for the application (generally based on OS/platform focus of your window)
IMGUI_API void AddInputCharacter(unsigned int c); // Queue a new character input IMGUI_API void AddInputCharacter(unsigned int c); // Queue a new character input
@ -2106,8 +2106,8 @@ struct ImGuiIO
// (reading from those variables is fair game, as they are extremely unlikely to be moving anywhere) // (reading from those variables is fair game, as they are extremely unlikely to be moving anywhere)
ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX, -FLT_MAX) if mouse is unavailable (on another screen, etc.) ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX, -FLT_MAX) if mouse is unavailable (on another screen, etc.)
bool MouseDown[5]; // Mouse buttons: 0=left, 1=right, 2=middle + extras (ImGuiMouseButton_COUNT == 5). Dear ImGui mostly uses left and right buttons. Other buttons allow us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. bool MouseDown[5]; // Mouse buttons: 0=left, 1=right, 2=middle + extras (ImGuiMouseButton_COUNT == 5). Dear ImGui mostly uses left and right buttons. Other buttons allow us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API.
float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text. float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text. >0 scrolls Up, <0 scrolls Down. Hold SHIFT to turn vertical scroll into horizontal scroll.
float MouseWheelH; // Mouse wheel Horizontal. Most users don't have a mouse with a horizontal wheel, may not be filled by all backends. float MouseWheelH; // Mouse wheel Horizontal. >0 scrolls Left, <0 scrolls Right. Most users don't have a mouse with a horizontal wheel, may not be filled by all backends.
ImGuiID MouseHoveredViewport; // (Optional) Modify using io.AddMouseViewportEvent(). With multi-viewports: viewport the OS mouse is hovering. If possible _IGNORING_ viewports with the ImGuiViewportFlags_NoInputs flag is much better (few backends can handle that). Set io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport if you can provide this info. If you don't imgui will infer the value using the rectangles and last focused time of the viewports it knows about (ignoring other OS windows). ImGuiID MouseHoveredViewport; // (Optional) Modify using io.AddMouseViewportEvent(). With multi-viewports: viewport the OS mouse is hovering. If possible _IGNORING_ viewports with the ImGuiViewportFlags_NoInputs flag is much better (few backends can handle that). Set io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport if you can provide this info. If you don't imgui will infer the value using the rectangles and last focused time of the viewports it knows about (ignoring other OS windows).
bool KeyCtrl; // Keyboard modifier down: Control bool KeyCtrl; // Keyboard modifier down: Control
bool KeyShift; // Keyboard modifier down: Shift bool KeyShift; // Keyboard modifier down: Shift

View File

@ -511,6 +511,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges); ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges);
ImGui::SameLine(); HelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback."); ImGui::SameLine(); HelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback.");
ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly); ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly);
ImGui::Checkbox("io.ConfigMacOSXBehaviors", &io.ConfigMacOSXBehaviors);
ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor); ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
ImGui::SameLine(); HelpMarker("Instruct Dear ImGui to render a mouse cursor itself. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something)."); ImGui::SameLine(); HelpMarker("Instruct Dear ImGui to render a mouse cursor itself. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
ImGui::Text("Also see Style->Rendering for rendering options."); ImGui::Text("Also see Style->Rendering for rendering options.");
@ -668,20 +669,41 @@ static void ShowDemoWindowWidgets()
ImGui::SameLine(); ImGui::SameLine();
ImGui::Text("%d", counter); ImGui::Text("%d", counter);
ImGui::Separator();
ImGui::LabelText("label", "Value");
{ {
// Using the _simplified_ one-liner Combo() api here // Tooltips
// See "Combo" section for examples of how to use the more flexible BeginCombo()/EndCombo() api. IMGUI_DEMO_MARKER("Widgets/Basic/Tooltips");
IMGUI_DEMO_MARKER("Widgets/Basic/Combo"); //ImGui::AlignTextToFramePadding();
const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIIIIII", "JJJJ", "KKKKKKK" }; ImGui::Text("Tooltips:");
static int item_current = 0;
ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items)); ImGui::SameLine();
ImGui::SameLine(); HelpMarker( ImGui::SmallButton("Button");
"Using the simplified one-liner Combo API here.\nRefer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API."); if (ImGui::IsItemHovered())
ImGui::SetTooltip("I am a tooltip");
ImGui::SameLine();
ImGui::SmallButton("Fancy");
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("I am a fancy tooltip");
static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
ImGui::Text("Sin(time) = %f", sinf((float)ImGui::GetTime()));
ImGui::EndTooltip();
}
ImGui::SameLine();
ImGui::SmallButton("Delayed");
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) // With a delay
ImGui::SetTooltip("I am a tooltip with a delay.");
ImGui::SameLine();
HelpMarker(
"Tooltip are created by using the IsItemHovered() function over any kind of item.");
} }
ImGui::LabelText("label", "Value");
{ {
// To wire InputText() with std::string or any other custom string type, // To wire InputText() with std::string or any other custom string type,
// see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file. // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file.
@ -780,6 +802,17 @@ static void ShowDemoWindowWidgets()
ImGui::ColorEdit4("color 2", col2); ImGui::ColorEdit4("color 2", col2);
} }
{
// Using the _simplified_ one-liner Combo() api here
// See "Combo" section for examples of how to use the more flexible BeginCombo()/EndCombo() api.
IMGUI_DEMO_MARKER("Widgets/Basic/Combo");
const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIIIIII", "JJJJ", "KKKKKKK" };
static int item_current = 0;
ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
ImGui::SameLine(); HelpMarker(
"Using the simplified one-liner Combo API here.\nRefer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API.");
}
{ {
// Using the _simplified_ one-liner ListBox() api here // Using the _simplified_ one-liner ListBox() api here
// See "List boxes" section for examples of how to use the more flexible BeginListBox()/EndListBox() api. // See "List boxes" section for examples of how to use the more flexible BeginListBox()/EndListBox() api.
@ -791,40 +824,6 @@ static void ShowDemoWindowWidgets()
"Using the simplified one-liner ListBox API here.\nRefer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API."); "Using the simplified one-liner ListBox API here.\nRefer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API.");
} }
{
// Tooltips
IMGUI_DEMO_MARKER("Widgets/Basic/Tooltips");
ImGui::AlignTextToFramePadding();
ImGui::Text("Tooltips:");
ImGui::SameLine();
ImGui::Button("Button");
if (ImGui::IsItemHovered())
ImGui::SetTooltip("I am a tooltip");
ImGui::SameLine();
ImGui::Button("Fancy");
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("I am a fancy tooltip");
static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
ImGui::Text("Sin(time) = %f", sinf((float)ImGui::GetTime()));
ImGui::EndTooltip();
}
ImGui::SameLine();
ImGui::Button("Delayed");
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) // Delay best used on items that highlight on hover, so this not a great example!
ImGui::SetTooltip("I am a tooltip with a delay.");
ImGui::SameLine();
HelpMarker(
"Tooltip are created by using the IsItemHovered() function over any kind of item.");
}
ImGui::TreePop(); ImGui::TreePop();
} }
@ -1084,12 +1083,14 @@ static void ShowDemoWindowWidgets()
float my_tex_w = (float)io.Fonts->TexWidth; float my_tex_w = (float)io.Fonts->TexWidth;
float my_tex_h = (float)io.Fonts->TexHeight; float my_tex_h = (float)io.Fonts->TexHeight;
{ {
static bool use_text_color_for_tint = false;
ImGui::Checkbox("Use Text Color for Tint", &use_text_color_for_tint);
ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h); ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
ImVec2 pos = ImGui::GetCursorScreenPos(); ImVec2 pos = ImGui::GetCursorScreenPos();
ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left
ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right
ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint ImVec4 tint_col = use_text_color_for_tint ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f); // 50% opaque white ImVec4 border_col = ImGui::GetStyleColorVec4(ImGuiCol_Border);
ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, tint_col, border_col); ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, tint_col, border_col);
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
{ {
@ -6259,7 +6260,6 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f"); ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f");
ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f"); ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f"); ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
ImGui::SliderFloat("LogSliderDeadzone", &style.LogSliderDeadzone, 0.0f, 12.0f, "%.0f");
ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f"); ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f");
ImGui::Text("Alignment"); ImGui::Text("Alignment");
ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f"); ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
@ -6274,6 +6274,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
ImGui::Text("Safe Area Padding"); ImGui::Text("Safe Area Padding");
ImGui::SameLine(); HelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured)."); ImGui::SameLine(); HelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f"); ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f");
ImGui::SliderFloat("LogSliderDeadzone", &style.LogSliderDeadzone, 0.0f, 12.0f, "%.0f");
ImGui::EndTabItem(); ImGui::EndTabItem();
} }

View File

@ -714,7 +714,7 @@ void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, c
// We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds. // We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds.
void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, ImDrawFlags flags, float thickness) void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, ImDrawFlags flags, float thickness)
{ {
if (points_count < 2) if (points_count < 2 || (col & IM_COL32_A_MASK) == 0)
return; return;
const bool closed = (flags & ImDrawFlags_Closed) != 0; const bool closed = (flags & ImDrawFlags_Closed) != 0;
@ -972,7 +972,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
// - Filled shapes must always use clockwise winding order. The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing. // - Filled shapes must always use clockwise winding order. The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing.
void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col) void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col)
{ {
if (points_count < 3) if (points_count < 3 || (col & IM_COL32_A_MASK) == 0)
return; return;
const ImVec2 uv = _Data->TexUvWhitePixel; const ImVec2 uv = _Data->TexUvWhitePixel;
@ -3581,19 +3581,17 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im
while (y + line_height < clip_rect.y && s < text_end) while (y + line_height < clip_rect.y && s < text_end)
{ {
const char* line_end = (const char*)memchr(s, '\n', text_end - s); const char* line_end = (const char*)memchr(s, '\n', text_end - s);
if (!line_end)
line_end = text_end;
if (word_wrap_enabled) if (word_wrap_enabled)
{ {
// FIXME-OPT: This is not optimal as do first do a search for \n before calling CalcWordWrapPositionA(). // FIXME-OPT: This is not optimal as do first do a search for \n before calling CalcWordWrapPositionA().
// If the specs for CalcWordWrapPositionA() were reworked to optionally return on \n we could combine both. // If the specs for CalcWordWrapPositionA() were reworked to optionally return on \n we could combine both.
// However it is still better than nothing performing the fast-forward! // However it is still better than nothing performing the fast-forward!
s = CalcWordWrapPositionA(scale, s, line_end, wrap_width); s = CalcWordWrapPositionA(scale, s, line_end ? line_end : text_end, wrap_width);
s = CalcWordWrapNextLineStartA(s, text_end); s = CalcWordWrapNextLineStartA(s, text_end);
} }
else else
{ {
s = line_end + 1; s = line_end ? line_end + 1 : text_end;
} }
y += line_height; y += line_height;
} }

View File

@ -1,10 +1,12 @@
// dear imgui, v1.89.3 WIP // dear imgui, v1.89.3 WIP
// (internal structures/api) // (internal structures/api)
// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
// Set: // To implement maths operators for ImVec2 (disabled by default to not conflict with using IM_VEC2_CLASS_EXTRA with your own math types+operators), use:
// #define IMGUI_DEFINE_MATH_OPERATORS /*
// To implement maths operators for ImVec2 (disabled by default to not collide with using IM_VEC2_CLASS_EXTRA along with your own math types+operators) #define IMGUI_DEFINE_MATH_OPERATORS
#include "imgui_internal.h"
*/
/* /*
@ -1846,25 +1848,17 @@ enum ImGuiDebugLogFlags_
struct ImGuiMetricsConfig struct ImGuiMetricsConfig
{ {
bool ShowDebugLog; bool ShowDebugLog = false;
bool ShowStackTool; bool ShowStackTool = false;
bool ShowWindowsRects; bool ShowWindowsRects = false;
bool ShowWindowsBeginOrder; bool ShowWindowsBeginOrder = false;
bool ShowTablesRects; bool ShowTablesRects = false;
bool ShowDrawCmdMesh; bool ShowDrawCmdMesh = true;
bool ShowDrawCmdBoundingBoxes; bool ShowDrawCmdBoundingBoxes = true;
bool ShowDockingNodes; bool ShowAtlasTintedWithTextColor = false;
int ShowWindowsRectsType; bool ShowDockingNodes = false;
int ShowTablesRectsType; int ShowWindowsRectsType = -1;
int ShowTablesRectsType = -1;
ImGuiMetricsConfig()
{
ShowDebugLog = ShowStackTool = ShowWindowsRects = ShowWindowsBeginOrder = ShowTablesRects = false;
ShowDrawCmdMesh = true;
ShowDrawCmdBoundingBoxes = true;
ShowDockingNodes = false;
ShowWindowsRectsType = ShowTablesRectsType = -1;
}
}; };
struct ImGuiStackLevelInfo struct ImGuiStackLevelInfo
@ -2621,7 +2615,7 @@ struct ImGuiTabItem
float RequestedWidth; // Width optionally requested by caller, -1.0f is unused float RequestedWidth; // Width optionally requested by caller, -1.0f is unused
ImS32 NameOffset; // When Window==NULL, offset to name within parent ImGuiTabBar::TabsNames ImS32 NameOffset; // When Window==NULL, offset to name within parent ImGuiTabBar::TabsNames
ImS16 BeginOrder; // BeginTabItem() order, used to re-order tabs after toggling ImGuiTabBarFlags_Reorderable ImS16 BeginOrder; // BeginTabItem() order, used to re-order tabs after toggling ImGuiTabBarFlags_Reorderable
ImS16 IndexDuringLayout; // Index only used during TabBarLayout() ImS16 IndexDuringLayout; // Index only used during TabBarLayout(). Tabs gets reordered so 'Tabs[n].IndexDuringLayout == n' but may mismatch during additions.
bool WantClose; // Marked as closed by SetTabItemClosed() bool WantClose; // Marked as closed by SetTabItemClosed()
ImGuiTabItem() { memset(this, 0, sizeof(*this)); LastFrameVisible = LastFrameSelected = -1; RequestedWidth = -1.0f; NameOffset = -1; BeginOrder = IndexDuringLayout = -1; } ImGuiTabItem() { memset(this, 0, sizeof(*this)); LastFrameVisible = LastFrameSelected = -1; RequestedWidth = -1.0f; NameOffset = -1; BeginOrder = IndexDuringLayout = -1; }
@ -2663,14 +2657,6 @@ struct IMGUI_API ImGuiTabBar
ImGuiTextBuffer TabsNames; // For non-docking tab bar we re-append names in a contiguous buffer. ImGuiTextBuffer TabsNames; // For non-docking tab bar we re-append names in a contiguous buffer.
ImGuiTabBar(); ImGuiTabBar();
int GetTabOrder(const ImGuiTabItem* tab) const { return Tabs.index_from_ptr(tab); }
const char* GetTabName(const ImGuiTabItem* tab) const
{
if (tab->Window)
return tab->Window->Name;
IM_ASSERT(tab->NameOffset != -1 && tab->NameOffset < TabsNames.Buf.Size);
return TabsNames.Buf.Data + tab->NameOffset;
}
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -3328,14 +3314,20 @@ namespace ImGui
IMGUI_API ImGuiTableSettings* TableSettingsFindByID(ImGuiID id); IMGUI_API ImGuiTableSettings* TableSettingsFindByID(ImGuiID id);
// Tab Bars // Tab Bars
inline ImGuiTabBar* GetCurrentTabBar() { ImGuiContext& g = *GImGui; return g.CurrentTabBar; }
IMGUI_API bool BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags, ImGuiDockNode* dock_node); IMGUI_API bool BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags, ImGuiDockNode* dock_node);
IMGUI_API ImGuiTabItem* TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id); IMGUI_API ImGuiTabItem* TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id);
IMGUI_API ImGuiTabItem* TabBarFindTabByOrder(ImGuiTabBar* tab_bar, int order);
IMGUI_API ImGuiTabItem* TabBarFindMostRecentlySelectedTabForActiveWindow(ImGuiTabBar* tab_bar); IMGUI_API ImGuiTabItem* TabBarFindMostRecentlySelectedTabForActiveWindow(ImGuiTabBar* tab_bar);
IMGUI_API ImGuiTabItem* TabBarGetCurrentTab(ImGuiTabBar* tab_bar);
inline int TabBarGetTabOrder(ImGuiTabBar* tab_bar, ImGuiTabItem* tab) { return tab_bar->Tabs.index_from_ptr(tab); }
IMGUI_API const char* TabBarGetTabName(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
IMGUI_API void TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiTabItemFlags tab_flags, ImGuiWindow* window); IMGUI_API void TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiTabItemFlags tab_flags, ImGuiWindow* window);
IMGUI_API void TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id); IMGUI_API void TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id);
IMGUI_API void TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab); IMGUI_API void TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
IMGUI_API void TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int offset); IMGUI_API void TabBarQueueFocus(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
IMGUI_API void TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, ImVec2 mouse_pos); IMGUI_API void TabBarQueueReorder(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, int offset);
IMGUI_API void TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, ImVec2 mouse_pos);
IMGUI_API bool TabBarProcessReorder(ImGuiTabBar* tab_bar); IMGUI_API bool TabBarProcessReorder(ImGuiTabBar* tab_bar);
IMGUI_API bool TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags, ImGuiWindow* docked_window); IMGUI_API bool TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags, ImGuiWindow* docked_window);
IMGUI_API ImVec2 TabItemCalcSize(const char* label, bool has_close_button_or_unsaved_marker); IMGUI_API ImVec2 TabItemCalcSize(const char* label, bool has_close_button_or_unsaved_marker);
@ -3372,7 +3364,7 @@ namespace ImGui
IMGUI_API void TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags flags = 0); IMGUI_API void TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags flags = 0);
IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0); IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0); IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0);
IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col); IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0);
IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags); IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags);
IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value); IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value);
IMGUI_API bool CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value); IMGUI_API bool CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value);

View File

@ -274,7 +274,6 @@ void ImGui::TextV(const char* fmt, va_list args)
if (window->SkipItems) if (window->SkipItems)
return; return;
// FIXME-OPT: Handle the %s shortcut?
const char* text, *text_end; const char* text, *text_end;
ImFormatStringToTempBufferV(&text, &text_end, fmt, args); ImFormatStringToTempBufferV(&text, &text_end, fmt, args);
TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText); TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText);
@ -291,10 +290,7 @@ void ImGui::TextColored(const ImVec4& col, const char* fmt, ...)
void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args) void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args)
{ {
PushStyleColor(ImGuiCol_Text, col); PushStyleColor(ImGuiCol_Text, col);
if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0) TextV(fmt, args);
TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
else
TextV(fmt, args);
PopStyleColor(); PopStyleColor();
} }
@ -310,10 +306,7 @@ void ImGui::TextDisabledV(const char* fmt, va_list args)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);
if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0) TextV(fmt, args);
TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
else
TextV(fmt, args);
PopStyleColor(); PopStyleColor();
} }
@ -328,13 +321,10 @@ void ImGui::TextWrapped(const char* fmt, ...)
void ImGui::TextWrappedV(const char* fmt, va_list args) void ImGui::TextWrappedV(const char* fmt, va_list args)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
bool need_backup = (g.CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position if one is already set const bool need_backup = (g.CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position if one is already set
if (need_backup) if (need_backup)
PushTextWrapPos(0.0f); PushTextWrapPos(0.0f);
if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0) TextV(fmt, args);
TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
else
TextV(fmt, args);
if (need_backup) if (need_backup)
PopTextWrapPos(); PopTextWrapPos();
} }
@ -1048,7 +1038,7 @@ void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2&
// ImageButton() is flawed as 'id' is always derived from 'texture_id' (see #2464 #1390) // ImageButton() is flawed as 'id' is always derived from 'texture_id' (see #2464 #1390)
// We provide this internal helper to write your own variant while we figure out how to redesign the public ImageButton() API. // We provide this internal helper to write your own variant while we figure out how to redesign the public ImageButton() API.
bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col) bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
@ -1062,7 +1052,7 @@ bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size
return false; return false;
bool hovered, held; bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held); bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
// Render // Render
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
@ -1711,7 +1701,12 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags
if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8; if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8;
else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4; else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4;
else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20; else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20;
SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items))); ImVec2 constraint_min(0.0f, 0.0f), constraint_max(FLT_MAX, FLT_MAX);
if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0 || g.NextWindowData.SizeVal.x <= 0.0f) // Don't apply constraints if user specified a size
constraint_min.x = w;
if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0 || g.NextWindowData.SizeVal.y <= 0.0f)
constraint_max.y = CalcMaxPopupHeightFromItemCount(popup_max_height_in_items);
SetNextWindowSizeConstraints(constraint_min, constraint_max);
} }
// This is essentially a specialized version of BeginPopupEx() // This is essentially a specialized version of BeginPopupEx()
@ -4102,6 +4097,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
state->Stb.insert_mode = 1; // stb field name is indeed incorrect (see #2863) state->Stb.insert_mode = 1; // stb field name is indeed incorrect (see #2863)
} }
const bool is_osx = io.ConfigMacOSXBehaviors;
if (g.ActiveId != id && init_make_active) if (g.ActiveId != id && init_make_active)
{ {
IM_ASSERT(state && state->ID == id); IM_ASSERT(state && state->ID == id);
@ -4124,6 +4120,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
SetKeyOwner(ImGuiKey_PageUp, id); SetKeyOwner(ImGuiKey_PageUp, id);
SetKeyOwner(ImGuiKey_PageDown, id); SetKeyOwner(ImGuiKey_PageDown, id);
} }
if (is_osx)
SetKeyOwner(ImGuiMod_Alt, id);
if (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput)) // Disable keyboard tabbing out as we will use the \t character. if (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput)) // Disable keyboard tabbing out as we will use the \t character.
SetKeyOwner(ImGuiKey_Tab, id); SetKeyOwner(ImGuiKey_Tab, id);
} }
@ -4193,7 +4191,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX; const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX;
const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y) : (g.FontSize * 0.5f)); const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y) : (g.FontSize * 0.5f));
const bool is_osx = io.ConfigMacOSXBehaviors;
if (select_all) if (select_all)
{ {
state->SelectAll(); state->SelectAll();
@ -4294,7 +4291,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
state->Stb.row_count_per_page = row_count_per_page; state->Stb.row_count_per_page = row_count_per_page;
const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0); const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0);
const bool is_osx = io.ConfigMacOSXBehaviors;
const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl
const bool is_startend_key_down = is_osx && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End const bool is_startend_key_down = is_osx && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End
@ -4323,7 +4319,16 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
else if (IsKeyPressed(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; } else if (IsKeyPressed(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; }
else if (IsKeyPressed(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); } else if (IsKeyPressed(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
else if (IsKeyPressed(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); } else if (IsKeyPressed(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
else if (IsKeyPressed(ImGuiKey_Delete) && !is_readonly && !is_cut) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); } else if (IsKeyPressed(ImGuiKey_Delete) && !is_readonly && !is_cut)
{
if (!state->HasSelection())
{
// OSX doesn't seem to have Super+Delete to delete until end-of-line, so we don't emulate that (as opposed to Super+Backspace)
if (is_wordmove_key_down)
state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT);
}
state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask);
}
else if (IsKeyPressed(ImGuiKey_Backspace) && !is_readonly) else if (IsKeyPressed(ImGuiKey_Backspace) && !is_readonly)
{ {
if (!state->HasSelection()) if (!state->HasSelection())
@ -7033,7 +7038,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
float w = label_size.x; float w = label_size.x;
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
pressed = Selectable("", menu_is_open, selectable_flags, ImVec2(w, 0.0f)); pressed = Selectable("", menu_is_open, selectable_flags, ImVec2(w, label_size.y));
RenderText(text_pos, label); RenderText(text_pos, label);
PopStyleVar(); PopStyleVar();
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
@ -7049,7 +7054,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame
float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
pressed = Selectable("", menu_is_open, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f)); pressed = Selectable("", menu_is_open, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y));
RenderText(text_pos, label); RenderText(text_pos, label);
if (icon_w > 0.0f) if (icon_w > 0.0f)
RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon); RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon);
@ -7241,7 +7246,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
float checkmark_w = IM_FLOOR(g.FontSize * 1.20f); float checkmark_w = IM_FLOOR(g.FontSize * 1.20f);
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame
float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f)); pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y));
if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible)
{ {
RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label); RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label);
@ -7293,12 +7298,19 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected,
// - TabBarCalcTabID() [Internal] // - TabBarCalcTabID() [Internal]
// - TabBarCalcMaxTabWidth() [Internal] // - TabBarCalcMaxTabWidth() [Internal]
// - TabBarFindTabById() [Internal] // - TabBarFindTabById() [Internal]
// - TabBarFindTabByOrder() [Internal]
// - TabBarFindMostRecentlySelectedTabForActiveWindow() [Internal]
// - TabBarGetCurrentTab() [Internal]
// - TabBarGetTabName() [Internal]
// - TabBarAddTab() [Internal] // - TabBarAddTab() [Internal]
// - TabBarRemoveTab() [Internal] // - TabBarRemoveTab() [Internal]
// - TabBarCloseTab() [Internal] // - TabBarCloseTab() [Internal]
// - TabBarScrollClamp() [Internal] // - TabBarScrollClamp() [Internal]
// - TabBarScrollToTab() [Internal] // - TabBarScrollToTab() [Internal]
// - TabBarQueueChangeTabOrder() [Internal] // - TabBarQueueFocus() [Internal]
// - TabBarQueueReorder() [Internal]
// - TabBarProcessReorderFromMousePos() [Internal]
// - TabBarProcessReorder() [Internal]
// - TabBarScrollingButtons() [Internal] // - TabBarScrollingButtons() [Internal]
// - TabBarTabListPopupButton() [Internal] // - TabBarTabListPopupButton() [Internal]
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -7424,6 +7436,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
tab_bar->ItemSpacingY = g.Style.ItemSpacing.y; tab_bar->ItemSpacingY = g.Style.ItemSpacing.y;
tab_bar->FramePadding = g.Style.FramePadding; tab_bar->FramePadding = g.Style.FramePadding;
tab_bar->TabsActiveCount = 0; tab_bar->TabsActiveCount = 0;
tab_bar->LastTabItemIdx = -1;
tab_bar->BeginCount = 1; tab_bar->BeginCount = 1;
// Set cursor pos in a way which only be used in the off-chance the user erroneously submits item before BeginTabItem(): items will overlap // Set cursor pos in a way which only be used in the off-chance the user erroneously submits item before BeginTabItem(): items will overlap
@ -7479,6 +7492,7 @@ void ImGui::EndTabBar()
if (tab_bar->BeginCount > 1) if (tab_bar->BeginCount > 1)
window->DC.CursorPos = tab_bar->BackupCursorPos; window->DC.CursorPos = tab_bar->BackupCursorPos;
tab_bar->LastTabItemIdx = -1;
if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0) if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0)
PopID(); PopID();
@ -7588,7 +7602,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
// Refresh tab width immediately, otherwise changes of style e.g. style.FramePadding.x would noticeably lag in the tab bar. // Refresh tab width immediately, otherwise changes of style e.g. style.FramePadding.x would noticeably lag in the tab bar.
// Additionally, when using TabBarAddTab() to manipulate tab bar order we occasionally insert new tabs that don't have a width yet, // Additionally, when using TabBarAddTab() to manipulate tab bar order we occasionally insert new tabs that don't have a width yet,
// and we cannot wait for the next BeginTabItem() call. We cannot compute this width within TabBarAddTab() because font size depends on the active window. // and we cannot wait for the next BeginTabItem() call. We cannot compute this width within TabBarAddTab() because font size depends on the active window.
const char* tab_name = tab_bar->GetTabName(tab); const char* tab_name = TabBarGetTabName(tab_bar, tab);
const bool has_close_button_or_unsaved_marker = (tab->Flags & ImGuiTabItemFlags_NoCloseButton) == 0 || (tab->Flags & ImGuiTabItemFlags_UnsavedDocument); const bool has_close_button_or_unsaved_marker = (tab->Flags & ImGuiTabItemFlags_NoCloseButton) == 0 || (tab->Flags & ImGuiTabItemFlags_UnsavedDocument);
tab->ContentWidth = (tab->RequestedWidth >= 0.0f) ? tab->RequestedWidth : TabItemCalcSize(tab_name, has_close_button_or_unsaved_marker).x; tab->ContentWidth = (tab->RequestedWidth >= 0.0f) ? tab->RequestedWidth : TabItemCalcSize(tab_name, has_close_button_or_unsaved_marker).x;
@ -7753,6 +7767,14 @@ ImGuiTabItem* ImGui::TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id)
return NULL; return NULL;
} }
// Order = visible order, not submission order! (which is tab->BeginOrder)
ImGuiTabItem* ImGui::TabBarFindTabByOrder(ImGuiTabBar* tab_bar, int order)
{
if (order < 0 || order >= tab_bar->Tabs.Size)
return NULL;
return &tab_bar->Tabs[order];
}
// FIXME: See references to #2304 in TODO.txt // FIXME: See references to #2304 in TODO.txt
ImGuiTabItem* ImGui::TabBarFindMostRecentlySelectedTabForActiveWindow(ImGuiTabBar* tab_bar) ImGuiTabItem* ImGui::TabBarFindMostRecentlySelectedTabForActiveWindow(ImGuiTabBar* tab_bar)
{ {
@ -7767,6 +7789,21 @@ ImGuiTabItem* ImGui::TabBarFindMostRecentlySelectedTabForActiveWindow(ImGuiTabBa
return most_recently_selected_tab; return most_recently_selected_tab;
} }
ImGuiTabItem* ImGui::TabBarGetCurrentTab(ImGuiTabBar* tab_bar)
{
if (tab_bar->LastTabItemIdx <= 0 || tab_bar->LastTabItemIdx >= tab_bar->Tabs.Size)
return NULL;
return &tab_bar->Tabs[tab_bar->LastTabItemIdx];
}
const char* ImGui::TabBarGetTabName(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
{
if (tab->Window)
return tab->Window->Name;
IM_ASSERT(tab->NameOffset != -1 && tab->NameOffset < tab_bar->TabsNames.Buf.Size);
return tab_bar->TabsNames.Buf.Data + tab->NameOffset;
}
// The purpose of this call is to register tab in advance so we can control their order at the time they appear. // The purpose of this call is to register tab in advance so we can control their order at the time they appear.
// Otherwise calling this is unnecessary as tabs are appending as needed by the BeginTabItem() function. // Otherwise calling this is unnecessary as tabs are appending as needed by the BeginTabItem() function.
void ImGui::TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiTabItemFlags tab_flags, ImGuiWindow* window) void ImGui::TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiTabItemFlags tab_flags, ImGuiWindow* window)
@ -7788,7 +7825,7 @@ void ImGui::TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiTabItemFlags tab_flags, ImGu
tab_bar->Tabs.push_back(new_tab); tab_bar->Tabs.push_back(new_tab);
} }
// The *TabId fields be already set by the docking system _before_ the actual TabItem was created, so we clear them regardless. // The *TabId fields are already set by the docking system _before_ the actual TabItem was created, so we clear them regardless.
void ImGui::TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id) void ImGui::TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id)
{ {
if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id)) if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id))
@ -7819,7 +7856,7 @@ void ImGui::TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
{ {
// Actually select before expecting closure attempt (on an UnsavedDocument tab user is expect to e.g. show a popup) // Actually select before expecting closure attempt (on an UnsavedDocument tab user is expect to e.g. show a popup)
if (tab_bar->VisibleTabId != tab->ID) if (tab_bar->VisibleTabId != tab->ID)
tab_bar->NextSelectedTabId = tab->ID; TabBarQueueFocus(tab_bar, tab);
} }
} }
@ -7840,7 +7877,7 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
float margin = g.FontSize * 1.0f; // When to scroll to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar) float margin = g.FontSize * 1.0f; // When to scroll to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar)
int order = tab_bar->GetTabOrder(tab); int order = TabBarGetTabOrder(tab_bar, tab);
// Scrolling happens only in the central section (leading/trailing sections are not scrolling) // Scrolling happens only in the central section (leading/trailing sections are not scrolling)
// FIXME: This is all confusing. // FIXME: This is all confusing.
@ -7864,7 +7901,12 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
} }
} }
void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int offset) void ImGui::TabBarQueueFocus(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
{
tab_bar->NextSelectedTabId = tab->ID;
}
void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, int offset)
{ {
IM_ASSERT(offset != 0); IM_ASSERT(offset != 0);
IM_ASSERT(tab_bar->ReorderRequestTabId == 0); IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
@ -7872,7 +7914,7 @@ void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, in
tab_bar->ReorderRequestOffset = (ImS16)offset; tab_bar->ReorderRequestOffset = (ImS16)offset;
} }
void ImGui::TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, const ImGuiTabItem* src_tab, ImVec2 mouse_pos) void ImGui::TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, ImGuiTabItem* src_tab, ImVec2 mouse_pos)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(tab_bar->ReorderRequestTabId == 0); IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
@ -7915,7 +7957,7 @@ bool ImGui::TabBarProcessReorder(ImGuiTabBar* tab_bar)
return false; return false;
//IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools //IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools
int tab2_order = tab_bar->GetTabOrder(tab1) + tab_bar->ReorderRequestOffset; int tab2_order = TabBarGetTabOrder(tab_bar, tab1) + tab_bar->ReorderRequestOffset;
if (tab2_order < 0 || tab2_order >= tab_bar->Tabs.Size) if (tab2_order < 0 || tab2_order >= tab_bar->Tabs.Size)
return false; return false;
@ -7975,7 +8017,7 @@ static ImGuiTabItem* ImGui::TabBarScrollingButtons(ImGuiTabBar* tab_bar)
if (select_dir != 0) if (select_dir != 0)
if (ImGuiTabItem* tab_item = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId)) if (ImGuiTabItem* tab_item = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId))
{ {
int selected_order = tab_bar->GetTabOrder(tab_item); int selected_order = TabBarGetTabOrder(tab_bar, tab_item);
int target_order = selected_order + select_dir; int target_order = selected_order + select_dir;
// Skip tab item buttons until another tab item is found or end is reached // Skip tab item buttons until another tab item is found or end is reached
@ -8027,7 +8069,7 @@ static ImGuiTabItem* ImGui::TabBarTabListPopupButton(ImGuiTabBar* tab_bar)
if (tab->Flags & ImGuiTabItemFlags_Button) if (tab->Flags & ImGuiTabItemFlags_Button)
continue; continue;
const char* tab_name = tab_bar->GetTabName(tab); const char* tab_name = TabBarGetTabName(tab_bar, tab);
if (Selectable(tab_name, tab_bar->SelectedTabId == tab->ID)) if (Selectable(tab_name, tab_bar->SelectedTabId == tab->ID))
tab_to_select = tab; tab_to_select = tab;
} }
@ -8194,9 +8236,9 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
{ {
if (tab_appearing && (tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs) && tab_bar->NextSelectedTabId == 0) if (tab_appearing && (tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs) && tab_bar->NextSelectedTabId == 0)
if (!tab_bar_appearing || tab_bar->SelectedTabId == 0) if (!tab_bar_appearing || tab_bar->SelectedTabId == 0)
tab_bar->NextSelectedTabId = id; // New tabs gets activated TabBarQueueFocus(tab_bar, tab); // New tabs gets activated
if ((flags & ImGuiTabItemFlags_SetSelected) && (tab_bar->SelectedTabId != id)) // _SetSelected can only be passed on explicit tab bar if ((flags & ImGuiTabItemFlags_SetSelected) && (tab_bar->SelectedTabId != id)) // _SetSelected can only be passed on explicit tab bar
tab_bar->NextSelectedTabId = id; TabBarQueueFocus(tab_bar, tab);
} }
// Lock visibility // Lock visibility
@ -8260,7 +8302,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
bool hovered, held; bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
if (pressed && !is_tab_button) if (pressed && !is_tab_button)
tab_bar->NextSelectedTabId = id; TabBarQueueFocus(tab_bar, tab);
// Transfer active id window so the active id is not owned by the dock host (as StartMouseMovingWindow() // Transfer active id window so the active id is not owned by the dock host (as StartMouseMovingWindow()
// will only do it on the drag). This allows FocusWindow() to be more conservative in how it clears active id. // will only do it on the drag). This allows FocusWindow() to be more conservative in how it clears active id.
@ -8317,7 +8359,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
if (distance_from_edge_y >= threshold_y) if (distance_from_edge_y >= threshold_y)
undocking_tab = true; undocking_tab = true;
if (drag_distance_from_edge_x > threshold_x) if (drag_distance_from_edge_x > threshold_x)
if ((drag_dir < 0 && tab_bar->GetTabOrder(tab) == 0) || (drag_dir > 0 && tab_bar->GetTabOrder(tab) == tab_bar->Tabs.Size - 1)) if ((drag_dir < 0 && TabBarGetTabOrder(tab_bar, tab) == 0) || (drag_dir > 0 && TabBarGetTabOrder(tab_bar, tab) == tab_bar->Tabs.Size - 1))
undocking_tab = true; undocking_tab = true;
} }
@ -8353,9 +8395,8 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
// Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget. // Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget.
const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup); const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
if (hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1))) if (hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)) && !is_tab_button)
if (!is_tab_button) TabBarQueueFocus(tab_bar, tab);
tab_bar->NextSelectedTabId = id;
if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton) if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)
flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton; flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;

View File

@ -24,7 +24,7 @@ See https://gist.github.com/ocornut/b3a9ecf13502fd818799a452969649ad
- Oversampling settins are ignored but also not so much necessary with the higher quality rendering. - Oversampling settins are ignored but also not so much necessary with the higher quality rendering.
### Comparaison ### Comparison
Small, thin anti-aliased fonts typically benefit a lot from FreeType's hinting: Small, thin anti-aliased fonts typically benefit a lot from FreeType's hinting:
![comparing_font_rasterizers](https://user-images.githubusercontent.com/8225057/107550178-fef87f00-6bd0-11eb-8d09-e2edb2f0ccfc.gif) ![comparing_font_rasterizers](https://user-images.githubusercontent.com/8225057/107550178-fef87f00-6bd0-11eb-8d09-e2edb2f0ccfc.gif)

View File

@ -43,13 +43,16 @@
#include FT_SYNTHESIS_H // <freetype/ftsynth.h> #include FT_SYNTHESIS_H // <freetype/ftsynth.h>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) #pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
#pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). #pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3).
#endif #endif
#if defined(__GNUC__) #ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
#pragma GCC diagnostic ignored "-Wsubobject-linkage" // warning: 'xxxx' has a field xxxx whose type uses the anonymous namespace
#endif #endif
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -348,7 +351,7 @@ namespace
IM_ASSERT(0 && "FreeTypeFont::BlitGlyph(): Unknown bitmap pixel mode!"); IM_ASSERT(0 && "FreeTypeFont::BlitGlyph(): Unknown bitmap pixel mode!");
} }
} }
} } // namespace
#ifndef STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds) #ifndef STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds)
#ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION #ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
@ -779,3 +782,11 @@ void ImGuiFreeType::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* u
GImGuiFreeTypeFreeFunc = free_func; GImGuiFreeTypeFreeFunc = free_func;
GImGuiFreeTypeAllocatorUserData = user_data; GImGuiFreeTypeAllocatorUserData = user_data;
} }
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#ifdef _MSC_VER
#pragma warning (pop)
#endif

View File

@ -8,6 +8,9 @@
// Before you include this file in *one* C++ file to create the implementation. // Before you include this file in *one* C++ file to create the implementation.
// Using this in your project will leak the contents of imgui_internal.h and ImVec2 operators in this compilation unit. // Using this in your project will leak the contents of imgui_internal.h and ImVec2 operators in this compilation unit.
#include "../../imgui.h" #include "../../imgui.h"
#ifdef IMGUI_ENABLE_FREETYPE
#include "../../misc/freetype/imgui_freetype.h"
#endif
#ifdef IMGUI_IMPLEMENTATION #ifdef IMGUI_IMPLEMENTATION
#include "../../imgui.cpp" #include "../../imgui.cpp"
@ -15,4 +18,7 @@
#include "../../imgui_draw.cpp" #include "../../imgui_draw.cpp"
#include "../../imgui_tables.cpp" #include "../../imgui_tables.cpp"
#include "../../imgui_widgets.cpp" #include "../../imgui_widgets.cpp"
#ifdef IMGUI_ENABLE_FREETYPE
#include "../../misc/freetype/imgui_freetype.cpp"
#endif
#endif #endif