Merge branch 'master' into docking (incl glfw use of GLFW_VERSION_COMBINED)

Note switched from GLFW_VERSION_REVISION * 10 to GLFW_VERSION_REVISION * 1
This commit is contained in:
ocornut 2022-10-24 22:58:25 +02:00
commit 375ae5dce4
11 changed files with 162 additions and 135 deletions

View File

@ -44,34 +44,3 @@ jobs:
pvs-studio-analyzer trace -- make WITH_EXTRA_WARNINGS=1 pvs-studio-analyzer trace -- make WITH_EXTRA_WARNINGS=1
pvs-studio-analyzer analyze -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log pvs-studio-analyzer analyze -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log
plog-converter -a 'GA:1,2;OP:1' -d V1071 -t errorfile -w pvs-studio.log plog-converter -a 'GA:1,2;OP:1' -d V1071 -t errorfile -w pvs-studio.log
Discord-CI:
runs-on: ubuntu-20.04
needs: [PVS-Studio]
if: always()
steps:
- uses: dearimgui/github_discord_notifier@latest
with:
discord-webhook: ${{ secrets.DISCORD_CI_WEBHOOK }}
github-token: ${{ github.token }}
action-task: discord-jobs
discord-filter: "'{{ github.branch }}'.match(/master|docking/g) != null && '{{ run.conclusion }}' != '{{ last_run.conclusion }}'"
discord-username: GitHub Actions
discord-job-new-failure-message: ''
discord-job-fixed-failure-message: ''
discord-job-new-failure-embed: |
{
"title": "`{{ job.name }}` job is failing on `{{ github.branch }}`!",
"description": "Commit [{{ github.context.payload.head_commit.title }}]({{ github.context.payload.head_commit.url }}) pushed to [{{ github.branch }}]({{ github.branch_url }}) broke static analysis [{{ job.name }}]({{ job.url }}) job.\nFailing steps: {{ failing_steps }}",
"url": "{{ job.url }}",
"color": "0xFF0000",
"timestamp": "{{ run.updated_at }}"
}
discord-job-fixed-failure-embed: |
{
"title": "`{{ github.branch }}` branch is no longer failing!",
"description": "Static analysis failures were fixed on [{{ github.branch }}]({{ github.branch_url }}) branch.",
"color": "0x00FF00",
"url": "{{ github.context.payload.head_commit.url }}",
"timestamp": "{{ run.completed_at }}"
}

View File

@ -608,7 +608,7 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) // By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
// If you would like to use this DX12 sample code but remove this dependency you can: // If you would like to use this DX12 sample code but remove this dependency you can:
// 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution] // 1) compile once, save the compiled shader blobs into a file or source code and assign them to psoDesc.VS/PS [preferred solution]
// 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
// See https://github.com/ocornut/imgui/pull/638 for sources and details. // See https://github.com/ocornut/imgui/pull/638 for sources and details.
@ -657,7 +657,7 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
}"; }";
if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), nullptr, nullptr, nullptr, "main", "vs_5_0", 0, 0, &vertexShaderBlob, nullptr))) if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), nullptr, nullptr, nullptr, "main", "vs_5_0", 0, 0, &vertexShaderBlob, nullptr)))
return false; // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
psoDesc.VS = { vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize() }; psoDesc.VS = { vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize() };
// Create the input layout // Create the input layout
@ -691,7 +691,7 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), nullptr, nullptr, nullptr, "main", "ps_5_0", 0, 0, &pixelShaderBlob, nullptr))) if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), nullptr, nullptr, nullptr, "main", "ps_5_0", 0, 0, &pixelShaderBlob, nullptr)))
{ {
vertexShaderBlob->Release(); vertexShaderBlob->Release();
return false; // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
} }
psoDesc.PS = { pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize() }; psoDesc.PS = { pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize() };
} }

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)
// 2022-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2022-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2022-10-18: Perform a dummy glfwGetError() read to cancel missing mouse cursors errors. Using GLFW_VERSION_COMBINED directly. (#5785)
// 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: 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).
// 2022-09-01: Inputs: Honor GLFW_CURSOR_DISABLED by not setting mouse position. // 2022-09-01: Inputs: Honor GLFW_CURSOR_DISABLED by not setting mouse position.
@ -82,27 +83,29 @@
#include <GLFW/glfw3native.h> // for glfwGetCocoaWindow() #include <GLFW/glfw3native.h> // for glfwGetCocoaWindow()
#endif #endif
#define GLFW_HAS_WINDOW_TOPMOST (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ GLFW_FLOATING // We gather version tests as define in order to easily see which features are version-dependent.
#define GLFW_HAS_WINDOW_HOVERED (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ GLFW_HOVERED #define GLFW_VERSION_COMBINED (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 + GLFW_VERSION_REVISION)
#define GLFW_HAS_WINDOW_ALPHA (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwSetWindowOpacity #define GLFW_HAS_WINDOW_TOPMOST (GLFW_VERSION_COMBINED >= 3200) // 3.2+ GLFW_FLOATING
#define GLFW_HAS_PER_MONITOR_DPI (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwGetMonitorContentScale #define GLFW_HAS_WINDOW_HOVERED (GLFW_VERSION_COMBINED >= 3300) // 3.3+ GLFW_HOVERED
#define GLFW_HAS_VULKAN (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ glfwCreateWindowSurface #define GLFW_HAS_WINDOW_ALPHA (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwSetWindowOpacity
#define GLFW_HAS_FOCUS_WINDOW (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ glfwFocusWindow #define GLFW_HAS_PER_MONITOR_DPI (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetMonitorContentScale
#define GLFW_HAS_FOCUS_ON_SHOW (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ GLFW_FOCUS_ON_SHOW #define GLFW_HAS_VULKAN (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwCreateWindowSurface
#define GLFW_HAS_MONITOR_WORK_AREA (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwGetMonitorWorkarea #define GLFW_HAS_FOCUS_WINDOW (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwFocusWindow
#define GLFW_HAS_OSX_WINDOW_POS_FIX (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 + GLFW_VERSION_REVISION * 10 >= 3310) // 3.3.1+ Fixed: Resizing window repositions it on MacOS #1553 #define GLFW_HAS_FOCUS_ON_SHOW (GLFW_VERSION_COMBINED >= 3300) // 3.3+ GLFW_FOCUS_ON_SHOW
#define GLFW_HAS_MONITOR_WORK_AREA (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetMonitorWorkarea
#define GLFW_HAS_OSX_WINDOW_POS_FIX (GLFW_VERSION_COMBINED >= 3301) // 3.3.1+ Fixed: Resizing window repositions it on MacOS #1553
#ifdef GLFW_RESIZE_NESW_CURSOR // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2019-11-29 (cursors defines) // FIXME: Remove when GLFW 3.4 is released? #ifdef GLFW_RESIZE_NESW_CURSOR // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2019-11-29 (cursors defines) // FIXME: Remove when GLFW 3.4 is released?
#define GLFW_HAS_NEW_CURSORS (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3400) // 3.4+ GLFW_RESIZE_ALL_CURSOR, GLFW_RESIZE_NESW_CURSOR, GLFW_RESIZE_NWSE_CURSOR, GLFW_NOT_ALLOWED_CURSOR #define GLFW_HAS_NEW_CURSORS (GLFW_VERSION_COMBINED >= 3400) // 3.4+ GLFW_RESIZE_ALL_CURSOR, GLFW_RESIZE_NESW_CURSOR, GLFW_RESIZE_NWSE_CURSOR, GLFW_NOT_ALLOWED_CURSOR
#else #else
#define GLFW_HAS_NEW_CURSORS (0) #define GLFW_HAS_NEW_CURSORS (0)
#endif #endif
#ifdef GLFW_MOUSE_PASSTHROUGH // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2020-07-17 (passthrough) #ifdef GLFW_MOUSE_PASSTHROUGH // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2020-07-17 (passthrough)
#define GLFW_HAS_MOUSE_PASSTHROUGH (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3400) // 3.4+ GLFW_MOUSE_PASSTHROUGH #define GLFW_HAS_MOUSE_PASSTHROUGH (GLFW_VERSION_COMBINED >= 3400) // 3.4+ GLFW_MOUSE_PASSTHROUGH
#else #else
#define GLFW_HAS_MOUSE_PASSTHROUGH (0) #define GLFW_HAS_MOUSE_PASSTHROUGH (0)
#endif #endif
#define GLFW_HAS_GAMEPAD_API (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwGetGamepadState() new api #define GLFW_HAS_GAMEPAD_API (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetGamepadState() new api
#define GLFW_HAS_GET_KEY_NAME (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ glfwGetKeyName() #define GLFW_HAS_GETKEYNAME (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwGetKeyName()
// GLFW data // GLFW data
enum GlfwClientApi enum GlfwClientApi
@ -328,7 +331,7 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo
static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode) static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
{ {
#if GLFW_HAS_GET_KEY_NAME && !defined(__EMSCRIPTEN__) #if GLFW_HAS_GETKEYNAME && !defined(__EMSCRIPTEN__)
// GLFW 3.1+ attempts to "untranslate" keys, which goes the opposite of what every other framework does, making using lettered shortcuts difficult. // GLFW 3.1+ attempts to "untranslate" keys, which goes the opposite of what every other framework does, making using lettered shortcuts difficult.
// (It had reasons to do so: namely GLFW is/was more likely to be used for WASD-type game controls rather than lettered shortcuts, but IHMO the 3.1 change could have been done differently) // (It had reasons to do so: namely GLFW is/was more likely to be used for WASD-type game controls rather than lettered shortcuts, but IHMO the 3.1 change could have been done differently)
// See https://github.com/glfw/glfw/issues/1502 for details. // See https://github.com/glfw/glfw/issues/1502 for details.
@ -495,6 +498,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
//printf("GLFW_VERSION: %d.%d.%d (%d)", GLFW_VERSION_MAJOR, GLFW_VERSION_MINOR, GLFW_VERSION_REVISION, GLFW_VERSION_COMBINED);
// Setup backend capabilities flags // Setup backend capabilities flags
ImGui_ImplGlfw_Data* bd = IM_NEW(ImGui_ImplGlfw_Data)(); ImGui_ImplGlfw_Data* bd = IM_NEW(ImGui_ImplGlfw_Data)();
@ -535,6 +539,9 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
#endif
#if (GLFW_VERSION_COMBINED >= 3300) // Eat errors (see #5785)
(void)glfwGetError(NULL);
#endif #endif
glfwSetErrorCallback(prev_error_callback); glfwSetErrorCallback(prev_error_callback);

View File

@ -144,7 +144,8 @@ Breaking changes:
- always uses style.FramePadding for padding, to be consistent with other buttons. You may use PushStyleVar() to alter this. - always uses style.FramePadding for padding, to be consistent with other buttons. You may use PushStyleVar() to alter this.
- As always we are keeping a redirection function available (will obsolete later). - As always we are keeping a redirection function available (will obsolete later).
- Removed the bizarre legacy default argument for 'TreePush(const void* ptr = NULL)'. (#1057) - Removed the bizarre legacy default argument for 'TreePush(const void* ptr = NULL)'. (#1057)
Must always pass a pointer value explicitly, NULL is ok. Must always pass a pointer value explicitly, NULL/nullptr is ok but require cast, e.g. TreePush((void*)nullptr);
If you used TreePush() replace with TreePush((void*)NULL);
- Commented out redirecting functions/enums names that were marked obsolete in 1.77 and 1.78 (June 2020): (#3361) - Commented out redirecting functions/enums names that were marked obsolete in 1.77 and 1.78 (June 2020): (#3361)
- DragScalar(), DragScalarN(), DragFloat(), DragFloat2(), DragFloat3(), DragFloat4() - DragScalar(), DragScalarN(), DragFloat(), DragFloat2(), DragFloat3(), DragFloat4()
- SliderScalar(), SliderScalarN(), SliderFloat(), SliderFloat2(), SliderFloat3(), SliderFloat4() - SliderScalar(), SliderScalarN(), SliderFloat(), SliderFloat2(), SliderFloat3(), SliderFloat4()
@ -202,6 +203,7 @@ Other Changes:
bar boundaries (bug in 1.88). (#5652). bar boundaries (bug in 1.88). (#5652).
- Tabs: Enforcing minimum size of 1.0f, fixed asserting on zero-tab widths. (#5572) - Tabs: Enforcing minimum size of 1.0f, fixed asserting on zero-tab widths. (#5572)
- Window: Fixed a potential crash when appending to a child window. (#5515, #3496, #4797) [@rokups] - Window: Fixed a potential crash when appending to a child window. (#5515, #3496, #4797) [@rokups]
- Window: Fixed an issue where uncollapsed a window would show a scrollbar for a frame.
- IO: Added ImGuiMod_Shortcut which is ImGuiMod_Super on Mac and ImGuiMod_Ctrl otherwise. (#456) - IO: Added ImGuiMod_Shortcut which is ImGuiMod_Super on Mac and ImGuiMod_Ctrl otherwise. (#456)
- IO: Added ImGuiKey_MouseXXX aliases for mouse buttons/wheel so all operations done on ImGuiKey - IO: Added ImGuiKey_MouseXXX aliases for mouse buttons/wheel so all operations done on ImGuiKey
can apply to mouse data as well. (#4921) can apply to mouse data as well. (#4921)
@ -220,6 +222,8 @@ Other Changes:
- Menus, Nav: Fixed not being able to close a menu with Left arrow when parent is not a popup. (#5730) - Menus, Nav: Fixed not being able to close a menu with Left arrow when parent is not a popup. (#5730)
- Menus, Nav: Fixed using left/right navigation when appending to an existing menu (multiple - Menus, Nav: Fixed using left/right navigation when appending to an existing menu (multiple
BeginMenu() call with same names). (#1207) BeginMenu() call with same names). (#1207)
- Menus: Fixed a one-frame issue where SetNextWindowXXX data are not consumed by a BeginMenu()
returning false (specifically )
- Nav: Fixed moving/resizing window with gamepad or keyboard when running at very high framerate. - Nav: Fixed moving/resizing window with gamepad or keyboard when running at very high framerate.
- Nav: Pressing Space/GamepadFaceDown on a repeating button uses the same repeating rate as a mouse hold. - Nav: Pressing Space/GamepadFaceDown on a repeating button uses the same repeating rate as a mouse hold.
- Nav: Fixed an issue opening a menu with Right key from a non-menu window. - Nav: Fixed an issue opening a menu with Right key from a non-menu window.
@ -243,6 +247,7 @@ Other Changes:
- Examples: Added all SDL examples to default VS solution. - Examples: Added all SDL examples to default VS solution.
- Examples: Win32: Always use RegisterClassW() to ensure windows are Unicode. (#5725) - Examples: Win32: Always use RegisterClassW() to ensure windows are Unicode. (#5725)
- Backends: GLFW: Honor GLFW_CURSOR_DISABLED by not setting mouse position. (#5625) [@scorpion-26] - Backends: GLFW: Honor GLFW_CURSOR_DISABLED by not setting mouse position. (#5625) [@scorpion-26]
- Backends: GLFW: Add glfwGetError() call on GLFW 3.3 to inhibit missing mouse cursor errors. (#5785) [@mitchellh]
- Backends: SDL: Disable SDL 2.0.22 new "auto capture" which prevents drag and drop across windows - Backends: SDL: Disable SDL 2.0.22 new "auto capture" which prevents drag and drop across windows
(e.g. for multi-viewport support) and don't capture mouse when drag and dropping. (#5710) (e.g. for multi-viewport support) and don't capture mouse when drag and dropping. (#5710)
- Backends: Win32: Convert WM_CHAR values with MultiByteToWideChar() when window class was - Backends: Win32: Convert WM_CHAR values with MultiByteToWideChar() when window class was

View File

@ -108,11 +108,6 @@
//#define IM_DEBUG_BREAK IM_ASSERT(0) //#define IM_DEBUG_BREAK IM_ASSERT(0)
//#define IM_DEBUG_BREAK __debugbreak() //#define IM_DEBUG_BREAK __debugbreak()
//---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(),
// (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.)
// This adds a small runtime cost which is why it is not enabled by default.
//#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
//---- Debug Tools: Enable slower asserts //---- Debug Tools: Enable slower asserts
//#define IMGUI_DEBUG_PARANOID //#define IMGUI_DEBUG_PARANOID

View File

@ -65,7 +65,7 @@ CODE
// [SECTION] MISC HELPERS/UTILITIES (Color functions) // [SECTION] MISC HELPERS/UTILITIES (Color functions)
// [SECTION] ImGuiStorage // [SECTION] ImGuiStorage
// [SECTION] ImGuiTextFilter // [SECTION] ImGuiTextFilter
// [SECTION] ImGuiTextBuffer // [SECTION] ImGuiTextBuffer, ImGuiTextIndex
// [SECTION] ImGuiListClipper // [SECTION] ImGuiListClipper
// [SECTION] STYLING // [SECTION] STYLING
// [SECTION] RENDER HELPERS // [SECTION] RENDER HELPERS
@ -401,7 +401,7 @@ CODE
the ImGuiKey_ModXXX were introduced in 1.87 and mostly used by backends. the ImGuiKey_ModXXX were introduced in 1.87 and mostly used by backends.
the ImGuiModFlags_XXX have been exposed in imgui.h but not really used by any public api only by third-party extensions. the ImGuiModFlags_XXX have been exposed in imgui.h but not really used by any public api only by third-party extensions.
exceptionally commenting out the older ImGuiKeyModFlags_XXX names ahead of obsolescence schedule to reduce confusion and because they were not meant to be used anyway. exceptionally commenting out the older ImGuiKeyModFlags_XXX names ahead of obsolescence schedule to reduce confusion and because they were not meant to be used anyway.
- 2022/09/12 (1.89) - removed the bizarre legacy default argument for 'TreePush(const void* ptr = NULL)', always pass a pointer value explicitly, NULL is ok. - 2022/09/12 (1.89) - removed the bizarre legacy default argument for 'TreePush(const void* ptr = NULL)', always pass a pointer value explicitly. NULL/nullptr is ok but require cast, e.g. TreePush((void*)nullptr);
- 2022/09/05 (1.89) - commented out redirecting functions/enums names that were marked obsolete in 1.77 and 1.78 (June 2020): - 2022/09/05 (1.89) - commented out redirecting functions/enums names that were marked obsolete in 1.77 and 1.78 (June 2020):
- DragScalar(), DragScalarN(), DragFloat(), DragFloat2(), DragFloat3(), DragFloat4(): For old signatures ending with (..., const char* format, float power = 1.0f) -> use (..., format ImGuiSliderFlags_Logarithmic) if power != 1.0f. - DragScalar(), DragScalarN(), DragFloat(), DragFloat2(), DragFloat3(), DragFloat4(): For old signatures ending with (..., const char* format, float power = 1.0f) -> use (..., format ImGuiSliderFlags_Logarithmic) if power != 1.0f.
- SliderScalar(), SliderScalarN(), SliderFloat(), SliderFloat2(), SliderFloat3(), SliderFloat4(): For old signatures ending with (..., const char* format, float power = 1.0f) -> use (..., format ImGuiSliderFlags_Logarithmic) if power != 1.0f. - SliderScalar(), SliderScalarN(), SliderFloat(), SliderFloat2(), SliderFloat3(), SliderFloat4(): For old signatures ending with (..., const char* format, float power = 1.0f) -> use (..., format ImGuiSliderFlags_Logarithmic) if power != 1.0f.
@ -868,7 +868,6 @@ CODE
#include "imgui_internal.h" #include "imgui_internal.h"
// System includes // System includes
#include <ctype.h> // toupper
#include <stdio.h> // vsnprintf, sscanf, printf #include <stdio.h> // vsnprintf, sscanf, printf
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
#include <stddef.h> // intptr_t #include <stddef.h> // intptr_t
@ -1670,14 +1669,14 @@ ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c,
int ImStricmp(const char* str1, const char* str2) int ImStricmp(const char* str1, const char* str2)
{ {
int d; int d;
while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } while ((d = ImToUpper(*str2) - ImToUpper(*str1)) == 0 && *str1) { str1++; str2++; }
return d; return d;
} }
int ImStrnicmp(const char* str1, const char* str2, size_t count) int ImStrnicmp(const char* str1, const char* str2, size_t count)
{ {
int d = 0; int d = 0;
while (count > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; count--; } while (count > 0 && (d = ImToUpper(*str2) - ImToUpper(*str1)) == 0 && *str1) { str1++; str2++; count--; }
return d; return d;
} }
@ -1744,14 +1743,14 @@ const char* ImStristr(const char* haystack, const char* haystack_end, const char
if (!needle_end) if (!needle_end)
needle_end = needle + strlen(needle); needle_end = needle + strlen(needle);
const char un0 = (char)toupper(*needle); const char un0 = (char)ImToUpper(*needle);
while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end)) while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end))
{ {
if (toupper(*haystack) == un0) if (ImToUpper(*haystack) == un0)
{ {
const char* b = needle + 1; const char* b = needle + 1;
for (const char* a = haystack + 1; b < needle_end; a++, b++) for (const char* a = haystack + 1; b < needle_end; a++, b++)
if (toupper(*a) != toupper(*b)) if (ImToUpper(*a) != ImToUpper(*b))
break; break;
if (b == needle_end) if (b == needle_end)
return haystack; return haystack;
@ -2515,7 +2514,7 @@ bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] ImGuiTextBuffer // [SECTION] ImGuiTextBuffer, ImGuiTextIndex
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// On some platform vsnprintf() takes va_list by reference and modifies it. // On some platform vsnprintf() takes va_list by reference and modifies it.
@ -2583,6 +2582,20 @@ void ImGuiTextBuffer::appendfv(const char* fmt, va_list args)
va_end(args_copy); va_end(args_copy);
} }
void ImGuiTextIndex::append(const char* base, int old_size, int new_size)
{
IM_ASSERT(old_size >= 0 && new_size >= old_size && new_size >= EndOffset);
if (old_size == new_size)
return;
if (EndOffset == 0 || base[EndOffset - 1] == '\n')
LineOffsets.push_back(EndOffset);
const char* base_end = base + new_size;
for (const char* p = base + old_size; (p = (const char*)memchr(p, '\n', base_end - p)) != 0; )
if (++p < base_end) // Don't push a trailing offset on last \n
LineOffsets.push_back((int)(intptr_t)(p - base));
EndOffset = ImMax(EndOffset, new_size);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] ImGuiListClipper // [SECTION] ImGuiListClipper
// This is currently not as flexible/powerful as it should be and really confusing/spaghetti, mostly because we changed // This is currently not as flexible/powerful as it should be and really confusing/spaghetti, mostly because we changed
@ -3797,8 +3810,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
// [DEBUG] Item Picker tool! // [DEBUG] Item Picker tool!
// We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making // We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making
// the cost of this tool near-zero. We can get slightly better call-stack and support picking non-hovered // the cost of this tool near-zero. We can get slightly better call-stack and support picking non-hovered
// items if we perform the test in ItemAdd(), but that would incur a small runtime cost. // items if we performed the test in ItemAdd(), but that would incur a small runtime cost.
// #define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX in imconfig.h if you want this check to also be performed in ItemAdd().
if (g.DebugItemPickerActive && g.HoveredIdPreviousFrame == id) if (g.DebugItemPickerActive && g.HoveredIdPreviousFrame == id)
GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255)); GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255));
if (g.DebugItemPickerBreakId == id) if (g.DebugItemPickerBreakId == id)
@ -3811,6 +3823,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
return true; return true;
} }
// FIXME: This is inlined/duplicated in ItemAdd()
bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id) bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -4993,6 +5006,7 @@ void ImGui::Shutdown()
} }
g.LogBuffer.clear(); g.LogBuffer.clear();
g.DebugLogBuf.clear(); g.DebugLogBuf.clear();
g.DebugLogIndex.clear();
g.Initialized = false; g.Initialized = false;
} }
@ -5614,7 +5628,7 @@ bool ImGui::IsAnyItemFocused()
bool ImGui::IsItemVisible() bool ImGui::IsItemVisible()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
return g.CurrentWindow->ClipRect.Overlaps(g.LastItemData.Rect); return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) != 0;
} }
bool ImGui::IsItemEdited() bool ImGui::IsItemEdited()
@ -6168,7 +6182,7 @@ static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& s
if (resize_rect.Min.x > resize_rect.Max.x) ImSwap(resize_rect.Min.x, resize_rect.Max.x); if (resize_rect.Min.x > resize_rect.Max.x) ImSwap(resize_rect.Min.x, resize_rect.Max.x);
if (resize_rect.Min.y > resize_rect.Max.y) ImSwap(resize_rect.Min.y, resize_rect.Max.y); if (resize_rect.Min.y > resize_rect.Max.y) ImSwap(resize_rect.Min.y, resize_rect.Max.y);
ImGuiID resize_grip_id = window->GetID(resize_grip_n); // == GetWindowResizeCornerID() ImGuiID resize_grip_id = window->GetID(resize_grip_n); // == GetWindowResizeCornerID()
KeepAliveID(resize_grip_id); ItemAdd(resize_rect, resize_grip_id, NULL, ImGuiItemFlags_NoNav);
ButtonBehavior(resize_rect, resize_grip_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus); ButtonBehavior(resize_rect, resize_grip_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
//GetForegroundDrawList(window)->AddRect(resize_rect.Min, resize_rect.Max, IM_COL32(255, 255, 0, 255)); //GetForegroundDrawList(window)->AddRect(resize_rect.Min, resize_rect.Max, IM_COL32(255, 255, 0, 255));
if (hovered || held) if (hovered || held)
@ -6204,7 +6218,7 @@ static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& s
bool hovered, held; bool hovered, held;
ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, WINDOWS_HOVER_PADDING); ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, WINDOWS_HOVER_PADDING);
ImGuiID border_id = window->GetID(border_n + 4); // == GetWindowResizeBorderID() ImGuiID border_id = window->GetID(border_n + 4); // == GetWindowResizeBorderID()
KeepAliveID(border_id); ItemAdd(border_rect, border_id, NULL, ImGuiItemFlags_NoNav);
ButtonBehavior(border_rect, border_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus); ButtonBehavior(border_rect, border_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
//GetForegroundDrawLists(window)->AddRect(border_rect.Min, border_rect.Max, IM_COL32(255, 255, 0, 255)); //GetForegroundDrawLists(window)->AddRect(border_rect.Min, border_rect.Max, IM_COL32(255, 255, 0, 255));
if ((hovered && g.HoveredIdTimer > WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER) || held) if ((hovered && g.HoveredIdTimer > WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER) || held)
@ -6869,6 +6883,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x); window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x);
window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y; window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y;
bool use_current_size_for_scrollbar_x = window_just_created;
bool use_current_size_for_scrollbar_y = window_just_created;
// Collapse window by double-clicking on title bar // Collapse window by double-clicking on title bar
// At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing
if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse) && !window->DockIsActive) if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse) && !window->DockIsActive)
@ -6880,6 +6897,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
if (window->WantCollapseToggle) if (window->WantCollapseToggle)
{ {
window->Collapsed = !window->Collapsed; window->Collapsed = !window->Collapsed;
if (!window->Collapsed)
use_current_size_for_scrollbar_y = true;
MarkIniSettingsDirty(window); MarkIniSettingsDirty(window);
} }
} }
@ -6893,8 +6912,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Calculate auto-fit size, handle automatic resize // Calculate auto-fit size, handle automatic resize
const ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, window->ContentSizeIdeal); const ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, window->ContentSizeIdeal);
bool use_current_size_for_scrollbar_x = window_just_created;
bool use_current_size_for_scrollbar_y = window_just_created;
if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed) if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed)
{ {
// Using SetNextWindowSize() overrides ImGuiWindowFlags_AlwaysAutoResize, so it can be used on tooltips/popups, etc. // Using SetNextWindowSize() overrides ImGuiWindowFlags_AlwaysAutoResize, so it can be used on tooltips/popups, etc.
@ -9285,25 +9302,19 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
// to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick). // to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick).
// We intentionally don't check if g.NavWindow != NULL because g.NavAnyRequest should only be set when it is non null. // We intentionally don't check if g.NavWindow != NULL because g.NavAnyRequest should only be set when it is non null.
// If we crash on a NULL g.NavWindow we need to fix the bug elsewhere. // If we crash on a NULL g.NavWindow we need to fix the bug elsewhere.
if (!(g.LastItemData.InFlags & ImGuiItemFlags_NoNav))
{
window->DC.NavLayersActiveMaskNext |= (1 << window->DC.NavLayerCurrent); window->DC.NavLayersActiveMaskNext |= (1 << window->DC.NavLayerCurrent);
if (g.NavId == id || g.NavAnyRequest) if (g.NavId == id || g.NavAnyRequest)
if (g.NavWindow->RootWindowForNav == window->RootWindowForNav) if (g.NavWindow->RootWindowForNav == window->RootWindowForNav)
if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened)) if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened))
NavProcessItem(); NavProcessItem();
}
// [DEBUG] People keep stumbling on this problem and using "" as identifier in the root of a window instead of "##something". // [DEBUG] People keep stumbling on this problem and using "" as identifier in the root of a window instead of "##something".
// Empty identifier are valid and useful in a small amount of cases, but 99.9% of the time you want to use "##something". // Empty identifier are valid and useful in a small amount of cases, but 99.9% of the time you want to use "##something".
// READ THE FAQ: https://dearimgui.org/faq // READ THE FAQ: https://dearimgui.org/faq
IM_ASSERT(id != window->ID && "Cannot have an empty ID at the root of a window. If you need an empty label, use ## and read the FAQ about how the ID Stack works!"); IM_ASSERT(id != window->ID && "Cannot have an empty ID at the root of a window. If you need an empty label, use ## and read the FAQ about how the ID Stack works!");
// [DEBUG] Item Picker tool, when enabling the "extended" version we perform the check in ItemAdd()
#ifdef IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
if (id == g.DebugItemPickerBreakId)
{
IM_DEBUG_BREAK();
g.DebugItemPickerBreakId = 0;
}
#endif
} }
g.NextItemData.Flags = ImGuiNextItemDataFlags_None; g.NextItemData.Flags = ImGuiNextItemDataFlags_None;
@ -9313,12 +9324,21 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
#endif #endif
// Clipping test // Clipping test
const bool is_clipped = IsClippedEx(bb, id); // (FIXME: This is a modified copy of IsClippedEx() so we can reuse the is_rect_visible value)
if (is_clipped) //const bool is_clipped = IsClippedEx(bb, id);
//if (is_clipped)
// return false;
const bool is_rect_visible = bb.Overlaps(window->ClipRect);
if (!is_rect_visible)
if (id == 0 || (id != g.ActiveId && id != g.NavId))
if (!g.LogEnabled)
return false; return false;
//if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG]
// We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them) // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them)
if (is_rect_visible)
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Visible;
if (IsMouseHoveringRect(bb.Min, bb.Max)) if (IsMouseHoveringRect(bb.Min, bb.Max))
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect;
return true; return true;
@ -10818,7 +10838,7 @@ static void ImGui::NavProcessItem()
if (is_tab_stop || (g.NavMoveFlags & ImGuiNavMoveFlags_FocusApi)) if (is_tab_stop || (g.NavMoveFlags & ImGuiNavMoveFlags_FocusApi))
NavProcessItemForTabbingRequest(id); NavProcessItemForTabbingRequest(id);
} }
else if ((g.NavId != id || (g.NavMoveFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & (ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNav))) else if ((g.NavId != id || (g.NavMoveFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & ImGuiItemFlags_Disabled))
{ {
ImGuiNavItemData* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther; ImGuiNavItemData* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
if (!is_tabbing) if (!is_tabbing)
@ -19092,7 +19112,7 @@ void ImGui::DebugNodeWindowsListByBeginStackParent(ImGuiWindow** windows, int wi
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] DEBUG LOG // [SECTION] DEBUG LOG WINDOW
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ImGui::DebugLog(const char* fmt, ...) void ImGui::DebugLog(const char* fmt, ...)
@ -19111,6 +19131,7 @@ void ImGui::DebugLogV(const char* fmt, va_list args)
g.DebugLogBuf.appendfv(fmt, args); g.DebugLogBuf.appendfv(fmt, args);
if (g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTTY) if (g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTTY)
IMGUI_DEBUG_PRINTF("%s", g.DebugLogBuf.begin() + old_size); IMGUI_DEBUG_PRINTF("%s", g.DebugLogBuf.begin() + old_size);
g.DebugLogIndex.append(g.DebugLogBuf.c_str(), old_size, g.DebugLogBuf.size());
} }
void ImGui::ShowDebugLogWindow(bool* p_open) void ImGui::ShowDebugLogWindow(bool* p_open)
@ -19137,12 +19158,24 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
SameLine(); CheckboxFlags("Viewport", &g.DebugLogFlags, ImGuiDebugLogFlags_EventViewport); SameLine(); CheckboxFlags("Viewport", &g.DebugLogFlags, ImGuiDebugLogFlags_EventViewport);
if (SmallButton("Clear")) if (SmallButton("Clear"))
{
g.DebugLogBuf.clear(); g.DebugLogBuf.clear();
g.DebugLogIndex.clear();
}
SameLine(); SameLine();
if (SmallButton("Copy")) if (SmallButton("Copy"))
SetClipboardText(g.DebugLogBuf.c_str()); SetClipboardText(g.DebugLogBuf.c_str());
BeginChild("##log", ImVec2(0.0f, 0.0f), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar); BeginChild("##log", ImVec2(0.0f, 0.0f), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar);
TextUnformatted(g.DebugLogBuf.begin(), g.DebugLogBuf.end()); // FIXME-OPT: Could use a line index, but TextUnformatted() has a semi-decent fast path for large text.
ImGuiListClipper clipper;
clipper.Begin(g.DebugLogIndex.size());
while (clipper.Step())
for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
{
const char* line_begin = g.DebugLogIndex.get_line_begin(g.DebugLogBuf.c_str(), line_no);
const char* line_end = g.DebugLogIndex.get_line_end(g.DebugLogBuf.c_str(), line_no);
TextUnformatted(line_begin, line_end);
}
if (GetScrollY() >= GetScrollMaxY()) if (GetScrollY() >= GetScrollMaxY())
SetScrollHereY(1.0f); SetScrollHereY(1.0f);
EndChild(); EndChild();

10
imgui.h
View File

@ -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 WIP" #define IMGUI_VERSION "1.89 WIP"
#define IMGUI_VERSION_NUM 18832 #define IMGUI_VERSION_NUM 18833
#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
@ -520,7 +520,7 @@ namespace ImGui
IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& tint_col = ImVec4(1, 1, 1, 1), const ImVec4& border_col = ImVec4(0, 0, 0, 0)); IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& tint_col = ImVec4(1, 1, 1, 1), const ImVec4& border_col = ImVec4(0, 0, 0, 0));
IMGUI_API bool ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); IMGUI_API bool ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1));
// Widgets: Combo Box // Widgets: Combo Box (Dropdown)
// - The BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() items. // - The BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() items.
// - The old Combo() api are helpers over BeginCombo()/EndCombo() which are kept available for convenience purpose. This is analogous to how ListBox are created. // - The old Combo() api are helpers over BeginCombo()/EndCombo() which are kept available for convenience purpose. This is analogous to how ListBox are created.
IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0); IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0);
@ -1404,8 +1404,9 @@ enum ImGuiSortDirection_
ImGuiSortDirection_Descending = 2 // Descending = 9->0, Z->A etc. ImGuiSortDirection_Descending = 2 // Descending = 9->0, Z->A etc.
}; };
// Keys value 0 to 511 are left unused as legacy native/opaque key values (< 1.87) // A key identifier (ImGuiKey_XXX or ImGuiMod_XXX value)
// Keys value >= 512 are named keys (>= 1.87) // All our named keys are >= 512. Keys value 0 to 511 are left unused as legacy native/opaque key values (< 1.87)
// Since >= 1.89 we increased typing (went from int to enum), some legacy code may need a cast to ImGuiKey.
enum ImGuiKey : int enum ImGuiKey : int
{ {
// Keyboard // Keyboard
@ -2089,6 +2090,7 @@ struct ImGuiIO
// Legacy: before 1.87, we required backend to fill io.KeyMap[] (imgui->native map) during initialization and io.KeysDown[] (native indices) every frame. // Legacy: before 1.87, we required backend to fill io.KeyMap[] (imgui->native map) during initialization and io.KeysDown[] (native indices) every frame.
// This is still temporarily supported as a legacy feature. However the new preferred scheme is for backend to call io.AddKeyEvent(). // This is still temporarily supported as a legacy feature. However the new preferred scheme is for backend to call io.AddKeyEvent().
// Old (<1.87): ImGui::IsKeyPressed(ImGui::GetIO().KeyMap[ImGuiKey_Space]) --> New (1.87+) ImGui::IsKeyPressed(ImGuiKey_Space)
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
int KeyMap[ImGuiKey_COUNT]; // [LEGACY] Input: map of indices into the KeysDown[512] entries array which represent your "native" keyboard state. The first 512 are now unused and should be kept zero. Legacy backend will write into KeyMap[] using ImGuiKey_ indices which are always >512. int KeyMap[ImGuiKey_COUNT]; // [LEGACY] Input: map of indices into the KeysDown[512] entries array which represent your "native" keyboard state. The first 512 are now unused and should be kept zero. Legacy backend will write into KeyMap[] using ImGuiKey_ indices which are always >512.
bool KeysDown[ImGuiKey_COUNT]; // [LEGACY] Input: Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). This used to be [512] sized. It is now ImGuiKey_COUNT to allow legacy io.KeysDown[GetKeyIndex(...)] to work without an overflow. bool KeysDown[ImGuiKey_COUNT]; // [LEGACY] Input: Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). This used to be [512] sized. It is now ImGuiKey_COUNT to allow legacy io.KeysDown[GetKeyIndex(...)] to work without an overflow.

View File

@ -1142,6 +1142,7 @@ static void ShowDemoWindowWidgets()
IMGUI_DEMO_MARKER("Widgets/Combo"); IMGUI_DEMO_MARKER("Widgets/Combo");
if (ImGui::TreeNode("Combo")) if (ImGui::TreeNode("Combo"))
{ {
// Combo Boxes are also called "Dropdown" in other systems
// Expose flags as checkbox for the demo // Expose flags as checkbox for the demo
static ImGuiComboFlags flags = 0; static ImGuiComboFlags flags = 0;
ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", &flags, ImGuiComboFlags_PopupAlignLeft); ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", &flags, ImGuiComboFlags_PopupAlignLeft);

View File

@ -312,6 +312,7 @@ namespace ImStb
// - Helper: ImSpan<>, ImSpanAllocator<> // - Helper: ImSpan<>, ImSpanAllocator<>
// - Helper: ImPool<> // - Helper: ImPool<>
// - Helper: ImChunkStream<> // - Helper: ImChunkStream<>
// - Helper: ImGuiTextIndex
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Helpers: Hashing // Helpers: Hashing
@ -345,6 +346,7 @@ IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end
IMGUI_API void ImStrTrimBlanks(char* str); IMGUI_API void ImStrTrimBlanks(char* str);
IMGUI_API const char* ImStrSkipBlank(const char* str); IMGUI_API const char* ImStrSkipBlank(const char* str);
IM_MSVC_RUNTIME_CHECKS_OFF IM_MSVC_RUNTIME_CHECKS_OFF
static inline char ImToUpper(char c) { return (c >= 'a' && c <= 'z') ? c &= ~32 : c; }
static inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; } static inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; }
static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; } static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; }
IM_MSVC_RUNTIME_CHECKS_RESTORE IM_MSVC_RUNTIME_CHECKS_RESTORE
@ -703,6 +705,20 @@ struct ImChunkStream
}; };
// Helper: ImGuiTextIndex<>
// Maintain a line index for a text buffer. This is a strong candidate to be moved into the public API.
struct ImGuiTextIndex
{
ImVector<int> LineOffsets;
int EndOffset = 0; // Because we don't own text buffer we need to maintain EndOffset (may bake in LineOffsets?)
void clear() { LineOffsets.clear(); EndOffset = 0; }
int size() { return LineOffsets.Size; }
const char* get_line_begin(const char* base, int n) { return base + LineOffsets[n]; }
const char* get_line_end(const char* base, int n) { return base + (n + 1 < LineOffsets.Size ? (LineOffsets[n + 1] - 1) : EndOffset); }
void append(const char* base, int old_size, int new_size);
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] ImDrawList support // [SECTION] ImDrawList support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -808,6 +824,7 @@ enum ImGuiItemStatusFlags_
ImGuiItemStatusFlags_Deactivated = 1 << 6, // Only valid if ImGuiItemStatusFlags_HasDeactivated is set. ImGuiItemStatusFlags_Deactivated = 1 << 6, // Only valid if ImGuiItemStatusFlags_HasDeactivated is set.
ImGuiItemStatusFlags_HoveredWindow = 1 << 7, // Override the HoveredWindow test to allow cross-window hover testing. ImGuiItemStatusFlags_HoveredWindow = 1 << 7, // Override the HoveredWindow test to allow cross-window hover testing.
ImGuiItemStatusFlags_FocusedByTabbing = 1 << 8, // Set when the Focusable item just got focused by Tabbing (FIXME: to be removed soon) ImGuiItemStatusFlags_FocusedByTabbing = 1 << 8, // Set when the Focusable item just got focused by Tabbing (FIXME: to be removed soon)
ImGuiItemStatusFlags_Visible = 1 << 9, // [WIP] Set when item is overlapping the current clipping rectangle (Used internally. Please don't use yet: API/system will change as we refactor Itemadd()).
#ifdef IMGUI_ENABLE_TEST_ENGINE #ifdef IMGUI_ENABLE_TEST_ENGINE
ImGuiItemStatusFlags_Openable = 1 << 20, // Item is an openable (e.g. TreeNode) ImGuiItemStatusFlags_Openable = 1 << 20, // Item is an openable (e.g. TreeNode)
@ -843,7 +860,7 @@ enum ImGuiButtonFlagsPrivate_
ImGuiButtonFlags_AlignTextBaseLine = 1 << 15, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine ImGuiButtonFlags_AlignTextBaseLine = 1 << 15, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine
ImGuiButtonFlags_NoKeyModifiers = 1 << 16, // disable mouse interaction if a key modifier is held ImGuiButtonFlags_NoKeyModifiers = 1 << 16, // disable mouse interaction if a key modifier is held
ImGuiButtonFlags_NoHoldingActiveId = 1 << 17, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) ImGuiButtonFlags_NoHoldingActiveId = 1 << 17, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only)
ImGuiButtonFlags_NoNavFocus = 1 << 18, // don't override navigation focus when activated ImGuiButtonFlags_NoNavFocus = 1 << 18, // don't override navigation focus when activated (FIXME: this is essentially used everytime an item uses ImGuiItemFlags_NoNav, but because legacy specs don't requires LastItemData to be set ButtonBehavior(), we can't poll g.LastItemData.InFlags)
ImGuiButtonFlags_NoHoveredOnFocus = 1 << 19, // don't report as hovered when nav focus is on this item ImGuiButtonFlags_NoHoveredOnFocus = 1 << 19, // don't report as hovered when nav focus is on this item
ImGuiButtonFlags_PressedOnMask_ = ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_PressedOnDragDropHold, ImGuiButtonFlags_PressedOnMask_ = ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_PressedOnDragDropHold,
ImGuiButtonFlags_PressedOnDefault_ = ImGuiButtonFlags_PressedOnClickRelease, ImGuiButtonFlags_PressedOnDefault_ = ImGuiButtonFlags_PressedOnClickRelease,
@ -2043,6 +2060,7 @@ struct ImGuiContext
// Debug Tools // Debug Tools
ImGuiDebugLogFlags DebugLogFlags; ImGuiDebugLogFlags DebugLogFlags;
ImGuiTextBuffer DebugLogBuf; ImGuiTextBuffer DebugLogBuf;
ImGuiTextIndex DebugLogIndex;
bool DebugItemPickerActive; // Item picker is active (started with DebugStartItemPicker()) bool DebugItemPickerActive; // Item picker is active (started with DebugStartItemPicker())
ImU8 DebugItemPickerMouseButton; ImU8 DebugItemPickerMouseButton;
ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this ID ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this ID

View File

@ -1171,8 +1171,8 @@ void ImGui::TableUpdateBorders(ImGuiTable* table)
ImGuiID column_id = TableGetColumnResizeID(table, column_n, table->InstanceCurrent); ImGuiID column_id = TableGetColumnResizeID(table, column_n, table->InstanceCurrent);
ImRect hit_rect(column->MaxX - hit_half_width, hit_y1, column->MaxX + hit_half_width, border_y2_hit); ImRect hit_rect(column->MaxX - hit_half_width, hit_y1, column->MaxX + hit_half_width, border_y2_hit);
ItemAdd(hit_rect, column_id, NULL, ImGuiItemFlags_NoNav);
//GetForegroundDrawList()->AddRect(hit_rect.Min, hit_rect.Max, IM_COL32(255, 0, 0, 100)); //GetForegroundDrawList()->AddRect(hit_rect.Min, hit_rect.Max, IM_COL32(255, 0, 0, 100));
KeepAliveID(column_id);
bool hovered = false, held = false; bool hovered = false, held = false;
bool pressed = ButtonBehavior(hit_rect, column_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_NoNavFocus); bool pressed = ButtonBehavior(hit_rect, column_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_NoNavFocus);
@ -4022,8 +4022,7 @@ void ImGui::EndColumns()
const ImGuiID column_id = columns->ID + ImGuiID(n); const ImGuiID column_id = columns->ID + ImGuiID(n);
const float column_hit_hw = COLUMNS_HIT_RECT_HALF_WIDTH; const float column_hit_hw = COLUMNS_HIT_RECT_HALF_WIDTH;
const ImRect column_hit_rect(ImVec2(x - column_hit_hw, y1), ImVec2(x + column_hit_hw, y2)); const ImRect column_hit_rect(ImVec2(x - column_hit_hw, y1), ImVec2(x + column_hit_hw, y2));
KeepAliveID(column_id); if (!ItemAdd(column_hit_rect, column_id, NULL, ImGuiItemFlags_NoNav))
if (IsClippedEx(column_hit_rect, column_id)) // FIXME: Can be removed or replaced with a lower-level test
continue; continue;
bool hovered = false, held = false; bool hovered = false, held = false;

View File

@ -41,7 +41,6 @@ Index of this file:
#include "imgui_internal.h" #include "imgui_internal.h"
// System includes // System includes
#include <ctype.h> // toupper
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
#include <stddef.h> // intptr_t #include <stddef.h> // intptr_t
#else #else
@ -932,8 +931,6 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
if (window->SkipItems) if (window->SkipItems)
return false; return false;
KeepAliveID(id);
const float bb_frame_width = bb_frame.GetWidth(); const float bb_frame_width = bb_frame.GetWidth();
const float bb_frame_height = bb_frame.GetHeight(); const float bb_frame_height = bb_frame.GetHeight();
if (bb_frame_width <= 0.0f || bb_frame_height <= 0.0f) if (bb_frame_width <= 0.0f || bb_frame_height <= 0.0f)
@ -965,6 +962,7 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
// Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar(). // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar().
bool held = false; bool held = false;
bool hovered = false; bool hovered = false;
ItemAdd(bb_frame, id, NULL, ImGuiItemFlags_NoNav);
ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus); ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus);
const ImS64 scroll_max = ImMax((ImS64)1, size_contents_v - size_avail_v); const ImS64 scroll_max = ImMax((ImS64)1, size_contents_v - size_avail_v);
@ -1484,11 +1482,7 @@ bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
const ImGuiItemFlags item_flags_backup = g.CurrentItemFlags; if (!ItemAdd(bb, id, NULL, ImGuiItemFlags_NoNav))
g.CurrentItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus;
bool item_add = ItemAdd(bb, id);
g.CurrentItemFlags = item_flags_backup;
if (!item_add)
return false; return false;
bool hovered, held; bool hovered, held;
@ -1759,7 +1753,7 @@ bool ImGui::BeginComboPreview()
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
ImGuiComboPreviewData* preview_data = &g.ComboPreviewData; ImGuiComboPreviewData* preview_data = &g.ComboPreviewData;
if (window->SkipItems || !window->ClipRect.Overlaps(g.LastItemData.Rect)) // FIXME: Because we don't have a ImGuiItemStatusFlags_Visible flag to test last ItemAdd() result if (window->SkipItems || !(g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible))
return false; return false;
IM_ASSERT(g.LastItemData.Rect.Min.x == preview_data->PreviewRect.Min.x && g.LastItemData.Rect.Min.y == preview_data->PreviewRect.Min.y); // Didn't call after BeginCombo/EndCombo block or forgot to pass ImGuiComboFlags_CustomPreview flag? IM_ASSERT(g.LastItemData.Rect.Min.x == preview_data->PreviewRect.Min.x && g.LastItemData.Rect.Min.y == preview_data->PreviewRect.Min.y); // Didn't call after BeginCombo/EndCombo block or forgot to pass ImGuiComboFlags_CustomPreview flag?
if (!window->ClipRect.Contains(preview_data->PreviewRect)) // Narrower test (optional) if (!window->ClipRect.Contains(preview_data->PreviewRect)) // Narrower test (optional)
@ -6844,7 +6838,7 @@ void ImGui::EndMenuBar()
// To do so we claim focus back, restore NavId and then process the movement request for yet another frame. // To do so we claim focus back, restore NavId and then process the movement request for yet another frame.
// This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth bothering) // This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth bothering)
const ImGuiNavLayer layer = ImGuiNavLayer_Menu; const ImGuiNavLayer layer = ImGuiNavLayer_Menu;
IM_ASSERT(window->DC.NavLayersActiveMaskNext & (1 << layer)); // Sanity check IM_ASSERT(window->DC.NavLayersActiveMaskNext & (1 << layer)); // Sanity check (FIXME: Seems unnecessary)
FocusWindow(window); FocusWindow(window);
SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]); SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection. g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection.
@ -6978,9 +6972,9 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
// Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu) // Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu)
// The first menu in a hierarchy isn't so hovering doesn't get across (otherwise e.g. resizing borders with ImGuiButtonFlags_FlattenChildren would react), but top-most BeginMenu() will bypass that limitation. // The first menu in a hierarchy isn't so hovering doesn't get across (otherwise e.g. resizing borders with ImGuiButtonFlags_FlattenChildren would react), but top-most BeginMenu() will bypass that limitation.
ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus; ImGuiWindowFlags window_flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus;
if (window->Flags & ImGuiWindowFlags_ChildMenu) if (window->Flags & ImGuiWindowFlags_ChildMenu)
flags |= ImGuiWindowFlags_ChildWindow; window_flags |= ImGuiWindowFlags_ChildWindow;
// If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin(). // If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin().
// We are relying on a O(N) search - so O(N log N) over the frame - which seems like the most efficient for the expected small amount of BeginMenu() calls per frame. // We are relying on a O(N) search - so O(N log N) over the frame - which seems like the most efficient for the expected small amount of BeginMenu() calls per frame.
@ -6988,7 +6982,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
if (g.MenusIdSubmittedThisFrame.contains(id)) if (g.MenusIdSubmittedThisFrame.contains(id))
{ {
if (menu_is_open) if (menu_is_open)
menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) menu_is_open = BeginPopupEx(id, window_flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
else else
g.NextWindowData.ClearFlags(); // we behave like Begin() and need to consume those values g.NextWindowData.ClearFlags(); // we behave like Begin() and need to consume those values
return menu_is_open; return menu_is_open;
@ -7125,23 +7119,23 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0)); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0));
PopID(); PopID();
if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size) if (want_open && !menu_is_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size)
{ {
// Don't recycle same menu level in the same frame, first close the other menu and yield for a frame. // Don't reopen/recycle same menu level in the same frame, first close the other menu and yield for a frame.
OpenPopup(label); OpenPopup(label);
return false;
} }
else if (want_open)
menu_is_open |= want_open; {
if (want_open) menu_is_open = true;
OpenPopup(label); OpenPopup(label);
}
if (menu_is_open) if (menu_is_open)
{ {
ImGuiLastItemData last_item_in_parent = g.LastItemData; ImGuiLastItemData last_item_in_parent = g.LastItemData;
SetNextWindowPos(popup_pos, ImGuiCond_Always); // Note: misleading: the value will serve as reference for FindBestWindowPosForPopup(), not actual pos. SetNextWindowPos(popup_pos, ImGuiCond_Always); // Note: misleading: the value will serve as reference for FindBestWindowPosForPopup(), not actual pos.
PushStyleVar(ImGuiStyleVar_ChildRounding, style.PopupRounding); // First level will use _PopupRounding, subsequent will use _ChildRounding PushStyleVar(ImGuiStyleVar_ChildRounding, style.PopupRounding); // First level will use _PopupRounding, subsequent will use _ChildRounding
menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) menu_is_open = BeginPopupEx(id, window_flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
PopStyleVar(); PopStyleVar();
if (menu_is_open) if (menu_is_open)
{ {
@ -7218,6 +7212,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
pressed = Selectable("", selected, selectable_flags, ImVec2(w, 0.0f)); pressed = Selectable("", selected, selectable_flags, ImVec2(w, 0.0f));
PopStyleVar(); PopStyleVar();
if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible)
RenderText(text_pos, label); RenderText(text_pos, label);
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().
} }
@ -7232,6 +7227,8 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
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, 0.0f));
if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible)
{
RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label); RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), 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);
@ -7244,6 +7241,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
if (selected) if (selected)
RenderCheckMark(window->DrawList, pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f); RenderCheckMark(window->DrawList, pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f);
} }
}
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0)); IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));
if (!enabled) if (!enabled)
EndDisabled(); EndDisabled();
@ -8119,7 +8117,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
if (p_open && !*p_open) if (p_open && !*p_open)
{ {
ItemAdd(ImRect(), id, NULL, ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus); ItemAdd(ImRect(), id, NULL, ImGuiItemFlags_NoNav);
return false; return false;
} }
@ -8202,7 +8200,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
// and then gets submitted again, the tabs will have 'tab_appearing=true' but 'tab_is_new=false'. // and then gets submitted again, the tabs will have 'tab_appearing=true' but 'tab_is_new=false'.
if (tab_appearing && (!tab_bar_appearing || tab_is_new)) if (tab_appearing && (!tab_bar_appearing || tab_is_new))
{ {
ItemAdd(ImRect(), id, NULL, ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus); ItemAdd(ImRect(), id, NULL, ImGuiItemFlags_NoNav);
if (is_tab_button) if (is_tab_button)
return false; return false;
return tab_contents_visible; return tab_contents_visible;