Browse Source

Merge branch 'master' into docking

# Conflicts:
#	backends/imgui_impl_vulkan.cpp
#	imgui_internal.h
pull/7100/head
ocornut 11 months ago
parent
commit
96b5b1724b
  1. 2
      backends/imgui_impl_android.cpp
  2. 4
      backends/imgui_impl_sdl3.cpp
  3. 3
      backends/imgui_impl_vulkan.cpp
  4. 8
      docs/CHANGELOG.txt
  5. 2
      examples/example_sdl3_sdlrenderer3/main.cpp
  6. 14
      examples/example_win32_opengl3/main.cpp
  7. 4
      imconfig.h
  8. 38
      imgui.cpp
  9. 17
      imgui.h
  10. 4
      imgui_demo.cpp
  11. 5
      imgui_internal.h
  12. 49
      imgui_widgets.cpp

2
backends/imgui_impl_android.cpp

@ -227,7 +227,7 @@ int32_t ImGui_ImplAndroid_HandleInputEvent(const AInputEvent* input_event)
// but we have to process them separately to identify the actual button pressed. This is done below via // but we have to process them separately to identify the actual button pressed. This is done below via
// AMOTION_EVENT_ACTION_BUTTON_PRESS/_RELEASE. Here, we only process "FINGER" input (and "UNKNOWN", as a fallback). // AMOTION_EVENT_ACTION_BUTTON_PRESS/_RELEASE. Here, we only process "FINGER" input (and "UNKNOWN", as a fallback).
int tool_type = AMotionEvent_getToolType(input_event, event_pointer_index); int tool_type = AMotionEvent_getToolType(input_event, event_pointer_index);
if (tool_type == AMOTION_EVENT_TOOL_TYPE_FINGER || tool_type == == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) if (tool_type == AMOTION_EVENT_TOOL_TYPE_FINGER || tool_type == AMOTION_EVENT_TOOL_TYPE_UNKNOWN)
{ {
io.AddMousePosEvent(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index)); io.AddMousePosEvent(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
io.AddMouseButtonEvent(0, event_action == AMOTION_EVENT_ACTION_DOWN); io.AddMouseButtonEvent(0, event_action == AMOTION_EVENT_ACTION_DOWN);

4
backends/imgui_impl_sdl3.cpp

@ -380,9 +380,9 @@ static void ImGui_ImplSDL3_SetupPlatformHandles(ImGuiViewport* viewport, SDL_Win
viewport->PlatformHandle = window; viewport->PlatformHandle = window;
viewport->PlatformHandleRaw = nullptr; viewport->PlatformHandleRaw = nullptr;
#if defined(__WIN32__) && !defined(__WINRT__) #if defined(__WIN32__) && !defined(__WINRT__)
viewport->PlatformHandleRaw = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.win32.hwnd", NULL); viewport->PlatformHandleRaw = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.win32.hwnd", nullptr);
#elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA) #elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA)
viewport->PlatformHandleRaw = (void*)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.window", NULL); viewport->PlatformHandleRaw = (void*)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.window", nullptr);
#endif #endif
} }

3
backends/imgui_impl_vulkan.cpp

@ -35,6 +35,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-11-29: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs vkDestroyCommandPool(). (#7075)
// 2023-11-10: *BREAKING CHANGE*: Removed parameter from ImGui_ImplVulkan_CreateFontsTexture(): backend now creates its own command-buffer to upload fonts. // 2023-11-10: *BREAKING CHANGE*: Removed parameter from ImGui_ImplVulkan_CreateFontsTexture(): backend now creates its own command-buffer to upload fonts.
// *BREAKING CHANGE*: Removed ImGui_ImplVulkan_DestroyFontUploadObjects() which is now unecessary as we create and destroy those objects in the backend. // *BREAKING CHANGE*: Removed ImGui_ImplVulkan_DestroyFontUploadObjects() which is now unecessary as we create and destroy those objects in the backend.
// ImGui_ImplVulkan_CreateFontsTexture() is automatically called by NewFrame() the first time. // ImGui_ImplVulkan_CreateFontsTexture() is automatically called by NewFrame() the first time.
@ -646,7 +647,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture()
info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
info.queueFamilyIndex = v->QueueFamily; info.queueFamilyIndex = v->QueueFamily;
vkCreateCommandPool(v->Device, &info, nullptr, &bd->FontCommandPool); vkCreateCommandPool(v->Device, &info, v->Allocator, &bd->FontCommandPool);
} }
if (bd->FontCommandBuffer == VK_NULL_HANDLE) if (bd->FontCommandBuffer == VK_NULL_HANDLE)
{ {

8
docs/CHANGELOG.txt

@ -51,10 +51,18 @@ Other changes:
- Drag and Drop: Fixed drop target highlight on items temporarily pushing a widened clip rect - Drag and Drop: Fixed drop target highlight on items temporarily pushing a widened clip rect
(namely Selectables and Treenodes using SpanAllColumn flag) so the highlight properly covers (namely Selectables and Treenodes using SpanAllColumn flag) so the highlight properly covers
all columns. (#7049, #4281, #3272) all columns. (#7049, #4281, #3272)
- Menus: Tweaked hover slack logic, adding a timer to avoid situations where a slow vertical
movements toward another parent BeginMenu() can keep the wrong child menu open. (#6671, #6926)
- Debug Tools: Added DebugFlashStyleColor() to identify a style color. Added to Style Editor.
- Misc: Added IMGUI_USER_H_FILENAME to change the path included when using
IMGUI_INCLUDE_IMGUI_USER_H. (#7039) [@bryceberger]
- Misc: Added extra courtesy ==/!= operators when IMGUI_DEFINE_MATH_OPERATORS is defined.
- Misc: Fixed text functions fast-path for handling "%s" and "%.*s" to handle null pointers gracefully, - Misc: Fixed text functions fast-path for handling "%s" and "%.*s" to handle null pointers gracefully,
like most printf implementations. (#7016, #3466, #6846) [@codefrog2002] like most printf implementations. (#7016, #3466, #6846) [@codefrog2002]
- Misc: Renamed some defines in imstb_textedit.h to avoid conflicts when using unity/jumbo builds - Misc: Renamed some defines in imstb_textedit.h to avoid conflicts when using unity/jumbo builds
on a codebase where another copy of the library is used. on a codebase where another copy of the library is used.
- Backends: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs
vkDestroyCommandPool(). (#7075) [@FoonTheRaccoon]
----------------------------------------------------------------------- -----------------------------------------------------------------------

2
examples/example_sdl3_sdlrenderer3/main.cpp

@ -42,7 +42,7 @@ int main(int, char**)
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1; return -1;
} }
SDL_Renderer* renderer = SDL_CreateRenderer(window, NULL, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); SDL_Renderer* renderer = SDL_CreateRenderer(window, nullptr, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
if (renderer == nullptr) if (renderer == nullptr)
{ {
SDL_Log("Error: SDL_CreateRenderer(): %s\n", SDL_GetError()); SDL_Log("Error: SDL_CreateRenderer(): %s\n", SDL_GetError());

14
examples/example_win32_opengl3/main.cpp

@ -74,9 +74,9 @@ int main(int, char**)
{ {
// Create application window // Create application window
//ImGui_ImplWin32_EnableDpiAwareness(); //ImGui_ImplWin32_EnableDpiAwareness();
WNDCLASSEXW wc = { sizeof(wc), CS_OWNDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, L"ImGui Example", NULL }; WNDCLASSEXW wc = { sizeof(wc), CS_OWNDC, WndProc, 0L, 0L, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, L"ImGui Example", nullptr };
::RegisterClassExW(&wc); ::RegisterClassExW(&wc);
HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Dear ImGui Win32+OpenGL3 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL); HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Dear ImGui Win32+OpenGL3 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, nullptr, nullptr, wc.hInstance, nullptr);
// Initialize OpenGL // Initialize OpenGL
if (!CreateDeviceWGL(hwnd, &g_MainWindow)) if (!CreateDeviceWGL(hwnd, &g_MainWindow))
@ -134,7 +134,7 @@ int main(int, char**)
// Load Fonts // 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. // - 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. // - 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). // - If the file cannot be loaded, the function will return a nullptr. 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. // - 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. // - 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. // - Read 'docs/FONTS.md' for more instructions and details.
@ -144,8 +144,8 @@ int main(int, char**)
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL); //IM_ASSERT(font != nullptr);
// Our state // Our state
bool show_demo_window = true; bool show_demo_window = true;
@ -159,7 +159,7 @@ int main(int, char**)
// Poll and handle messages (inputs, window resize, etc.) // Poll and handle messages (inputs, window resize, etc.)
// See the WndProc() function below for our to dispatch events to the Win32 backend. // See the WndProc() function below for our to dispatch events to the Win32 backend.
MSG msg; MSG msg;
while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE))
{ {
::TranslateMessage(&msg); ::TranslateMessage(&msg);
::DispatchMessage(&msg); ::DispatchMessage(&msg);
@ -270,7 +270,7 @@ bool CreateDeviceWGL(HWND hWnd, WGL_WindowData* data)
void CleanupDeviceWGL(HWND hWnd, WGL_WindowData* data) void CleanupDeviceWGL(HWND hWnd, WGL_WindowData* data)
{ {
wglMakeCurrent(NULL, NULL); wglMakeCurrent(nullptr, nullptr);
::ReleaseDC(hWnd, data->hDC); ::ReleaseDC(hWnd, data->hDC);
} }

4
imconfig.h

@ -50,12 +50,14 @@
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available //#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
//---- Include imgui_user.h at the end of imgui.h as a convenience //---- Include imgui_user.h at the end of imgui.h as a convenience
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
//#define IMGUI_INCLUDE_IMGUI_USER_H //#define IMGUI_INCLUDE_IMGUI_USER_H
//#define IMGUI_USER_H_FILENAME "my_folder/my_imgui_user.h"
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another) //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
//#define IMGUI_USE_BGRA_PACKED_COLOR //#define IMGUI_USE_BGRA_PACKED_COLOR
//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...) //---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
//#define IMGUI_USE_WCHAR32 //#define IMGUI_USE_WCHAR32
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version

38
imgui.cpp

@ -1111,6 +1111,7 @@ static void ErrorCheckNewFrameSanityChecks();
static void ErrorCheckEndFrameSanityChecks(); static void ErrorCheckEndFrameSanityChecks();
static void UpdateDebugToolItemPicker(); static void UpdateDebugToolItemPicker();
static void UpdateDebugToolStackQueries(); static void UpdateDebugToolStackQueries();
static void UpdateDebugToolFlashStyleColor();
// Inputs // Inputs
static void UpdateKeyboardInputs(); static void UpdateKeyboardInputs();
@ -3156,7 +3157,8 @@ void ImGui::PushStyleColor(ImGuiCol idx, ImU32 col)
backup.Col = idx; backup.Col = idx;
backup.BackupValue = g.Style.Colors[idx]; backup.BackupValue = g.Style.Colors[idx];
g.ColorStack.push_back(backup); g.ColorStack.push_back(backup);
g.Style.Colors[idx] = ColorConvertU32ToFloat4(col); if (g.DebugFlashStyleColorIdx != idx)
g.Style.Colors[idx] = ColorConvertU32ToFloat4(col);
} }
void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col) void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col)
@ -3166,7 +3168,8 @@ void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col)
backup.Col = idx; backup.Col = idx;
backup.BackupValue = g.Style.Colors[idx]; backup.BackupValue = g.Style.Colors[idx];
g.ColorStack.push_back(backup); g.ColorStack.push_back(backup);
g.Style.Colors[idx] = col; if (g.DebugFlashStyleColorIdx != idx)
g.Style.Colors[idx] = col;
} }
void ImGui::PopStyleColor(int count) void ImGui::PopStyleColor(int count)
@ -5019,6 +5022,7 @@ void ImGui::NewFrame()
// [DEBUG] Update debug features // [DEBUG] Update debug features
UpdateDebugToolItemPicker(); UpdateDebugToolItemPicker();
UpdateDebugToolStackQueries(); UpdateDebugToolStackQueries();
UpdateDebugToolFlashStyleColor();
if (g.DebugLocateFrames > 0 && --g.DebugLocateFrames == 0) if (g.DebugLocateFrames > 0 && --g.DebugLocateFrames == 0)
g.DebugLocateId = 0; g.DebugLocateId = 0;
if (g.DebugLogClipperAutoDisableFrames > 0 && --g.DebugLogClipperAutoDisableFrames == 0) if (g.DebugLogClipperAutoDisableFrames > 0 && --g.DebugLogClipperAutoDisableFrames == 0)
@ -19481,6 +19485,35 @@ void ImGui::DebugTextEncoding(const char* str)
EndTable(); EndTable();
} }
static void DebugFlashStyleColorStop()
{
ImGuiContext& g = *GImGui;
if (g.DebugFlashStyleColorIdx != ImGuiCol_COUNT)
g.Style.Colors[g.DebugFlashStyleColorIdx] = g.DebugFlashStyleColorBackup;
g.DebugFlashStyleColorIdx = ImGuiCol_COUNT;
}
// Flash a given style color for some + inhibit modifications of this color via PushStyleColor() calls.
void ImGui::DebugFlashStyleColor(ImGuiCol idx)
{
ImGuiContext& g = *GImGui;
DebugFlashStyleColorStop();
g.DebugFlashStyleColorTime = 0.5f;
g.DebugFlashStyleColorIdx = idx;
g.DebugFlashStyleColorBackup = g.Style.Colors[idx];
}
void ImGui::UpdateDebugToolFlashStyleColor()
{
ImGuiContext& g = *GImGui;
if (g.DebugFlashStyleColorTime <= 0.0f)
return;
ColorConvertHSVtoRGB(cosf(g.DebugFlashStyleColorTime * 6.0f) * 0.5f + 0.5f, 0.5f, 0.5f, g.Style.Colors[g.DebugFlashStyleColorIdx].x, g.Style.Colors[g.DebugFlashStyleColorIdx].y, g.Style.Colors[g.DebugFlashStyleColorIdx].z);
g.Style.Colors[g.DebugFlashStyleColorIdx].w = 1.0f;
if ((g.DebugFlashStyleColorTime -= g.IO.DeltaTime) <= 0.0f)
DebugFlashStyleColorStop();
}
// Avoid naming collision with imgui_demo.cpp's HelpMarker() for unity builds. // Avoid naming collision with imgui_demo.cpp's HelpMarker() for unity builds.
static void MetricsHelpMarker(const char* desc) static void MetricsHelpMarker(const char* desc)
{ {
@ -21054,6 +21087,7 @@ void ImGui::ShowIDStackToolWindow(bool*) {}
void ImGui::DebugHookIdInfo(ImGuiID, ImGuiDataType, const void*, const void*) {} void ImGui::DebugHookIdInfo(ImGuiID, ImGuiDataType, const void*, const void*) {}
void ImGui::UpdateDebugToolItemPicker() {} void ImGui::UpdateDebugToolItemPicker() {}
void ImGui::UpdateDebugToolStackQueries() {} void ImGui::UpdateDebugToolStackQueries() {}
void ImGui::UpdateDebugToolFlashStyleColor() {}
#endif // #ifndef IMGUI_DISABLE_DEBUG_TOOLS #endif // #ifndef IMGUI_DISABLE_DEBUG_TOOLS

17
imgui.h

@ -24,7 +24,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.90.1 WIP" #define IMGUI_VERSION "1.90.1 WIP"
#define IMGUI_VERSION_NUM 19001 #define IMGUI_VERSION_NUM 19002
#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
@ -122,6 +122,7 @@ Index of this file:
#endif #endif
#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' #pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx'
#pragma clang diagnostic ignored "-Wold-style-cast" #pragma clang diagnostic ignored "-Wold-style-cast"
#pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
#pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter #pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter
#elif defined(__GNUC__) #elif defined(__GNUC__)
@ -303,7 +304,7 @@ namespace ImGui
// Main // Main
IMGUI_API ImGuiIO& GetIO(); // access the IO structure (mouse/keyboard/gamepad inputs, time, various configuration options/flags) IMGUI_API ImGuiIO& GetIO(); // access the IO structure (mouse/keyboard/gamepad inputs, time, various configuration options/flags)
IMGUI_API ImGuiStyle& GetStyle(); // access the Style structure (colors, sizes). Always use PushStyleCol(), PushStyleVar() to modify style mid-frame! IMGUI_API ImGuiStyle& GetStyle(); // access the Style structure (colors, sizes). Always use PushStyleColor(), PushStyleVar() to modify style mid-frame!
IMGUI_API void NewFrame(); // start a new Dear ImGui frame, you can submit any command from this point until Render()/EndFrame(). IMGUI_API void NewFrame(); // start a new Dear ImGui frame, you can submit any command from this point until Render()/EndFrame().
IMGUI_API void EndFrame(); // ends the Dear ImGui frame. automatically called by Render(). If you don't need to render data (skipping rendering) you may call EndFrame() without Render()... but you'll have wasted CPU already! If you don't need to render, better to not create any windows and not call NewFrame() at all! IMGUI_API void EndFrame(); // ends the Dear ImGui frame. automatically called by Render(). If you don't need to render data (skipping rendering) you may call EndFrame() without Render()... but you'll have wasted CPU already! If you don't need to render, better to not create any windows and not call NewFrame() at all!
IMGUI_API void Render(); // ends the Dear ImGui frame, finalize the draw data. You can then get call GetDrawData(). IMGUI_API void Render(); // ends the Dear ImGui frame, finalize the draw data. You can then get call GetDrawData().
@ -994,6 +995,7 @@ namespace ImGui
// Debug Utilities // Debug Utilities
IMGUI_API void DebugTextEncoding(const char* text); IMGUI_API void DebugTextEncoding(const char* text);
IMGUI_API void DebugFlashStyleColor(ImGuiCol idx);
IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // This is called by IMGUI_CHECKVERSION() macro. IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // This is called by IMGUI_CHECKVERSION() macro.
// Memory Allocators // Memory Allocators
@ -2609,9 +2611,13 @@ static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x
static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; } static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }
static inline ImVec2& operator*=(ImVec2& lhs, const ImVec2& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; return lhs; } static inline ImVec2& operator*=(ImVec2& lhs, const ImVec2& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; return lhs; }
static inline ImVec2& operator/=(ImVec2& lhs, const ImVec2& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; return lhs; } static inline ImVec2& operator/=(ImVec2& lhs, const ImVec2& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; return lhs; }
static inline bool operator==(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; }
static inline bool operator!=(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y; }
static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); }
static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); }
static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); }
static inline bool operator==(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w; }
static inline bool operator!=(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z || lhs.w != rhs.w; }
IM_MSVC_RUNTIME_CHECKS_RESTORE IM_MSVC_RUNTIME_CHECKS_RESTORE
#endif #endif
@ -3539,9 +3545,14 @@ enum ImGuiModFlags_ { ImGuiModFlags_None = 0, ImGuiModFlags_Ctrl = ImGuiMod_Ctrl
#pragma warning (pop) #pragma warning (pop)
#endif #endif
// Include imgui_user.h at the end of imgui.h (convenient for user to only explicitly include vanilla imgui.h) // Include imgui_user.h at the end of imgui.h
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
#ifdef IMGUI_INCLUDE_IMGUI_USER_H #ifdef IMGUI_INCLUDE_IMGUI_USER_H
#ifdef IMGUI_USER_H_FILENAME
#include IMGUI_USER_H_FILENAME
#else
#include "imgui_user.h" #include "imgui_user.h"
#endif #endif
#endif
#endif // #ifndef IMGUI_DISABLE #endif // #ifndef IMGUI_DISABLE

4
imgui_demo.cpp

@ -6729,6 +6729,10 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
if (!filter.PassFilter(name)) if (!filter.PassFilter(name))
continue; continue;
ImGui::PushID(i); ImGui::PushID(i);
if (ImGui::Button("?"))
ImGui::DebugFlashStyleColor((ImGuiCol)i);
ImGui::SetItemTooltip("Flash given color to identify places where it is used.");
ImGui::SameLine();
ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags); ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0) if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
{ {

5
imgui_internal.h

@ -2147,6 +2147,7 @@ struct ImGuiContext
bool DebugShowGroupRects; bool DebugShowGroupRects;
// Shared stacks // Shared stacks
ImGuiCol DebugFlashStyleColorIdx; // (Keep close to ColorStack to share cache line)
ImVector<ImGuiColorMod> ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin() ImVector<ImGuiColorMod> ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin()
ImVector<ImGuiStyleMod> StyleVarStack; // Stack for PushStyleVar()/PopStyleVar() - inherited by Begin() ImVector<ImGuiStyleMod> StyleVarStack; // Stack for PushStyleVar()/PopStyleVar() - inherited by Begin()
ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont() - inherited by Begin() ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont() - inherited by Begin()
@ -2358,6 +2359,8 @@ struct ImGuiContext
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
float DebugFlashStyleColorTime;
ImVec4 DebugFlashStyleColorBackup;
ImGuiMetricsConfig DebugMetricsConfig; ImGuiMetricsConfig DebugMetricsConfig;
ImGuiIDStackTool DebugIDStackTool; ImGuiIDStackTool DebugIDStackTool;
ImGuiDebugAllocInfo DebugAllocInfo; ImGuiDebugAllocInfo DebugAllocInfo;
@ -2552,6 +2555,8 @@ struct ImGuiContext
DebugItemPickerActive = false; DebugItemPickerActive = false;
DebugItemPickerMouseButton = ImGuiMouseButton_Left; DebugItemPickerMouseButton = ImGuiMouseButton_Left;
DebugItemPickerBreakId = 0; DebugItemPickerBreakId = 0;
DebugFlashStyleColorTime = 0.0f;
DebugFlashStyleColorIdx = ImGuiCol_COUNT;
DebugHoveredDockNode = NULL; DebugHoveredDockNode = NULL;
memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame)); memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));

49
imgui_widgets.cpp

@ -1685,7 +1685,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
const ImGuiID id = window->GetID(label); const ImGuiID id = window->GetID(label);
IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together
if (flags & ImGuiComboFlags_WidthFitPreview) if (flags & ImGuiComboFlags_WidthFitPreview)
IM_ASSERT((flags & (ImGuiComboFlags_NoPreview | ImGuiComboFlags_CustomPreview)) == 0); IM_ASSERT((flags & (ImGuiComboFlags_NoPreview | (ImGuiComboFlags)ImGuiComboFlags_CustomPreview)) == 0);
const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight(); const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImVec2 label_size = CalcTextSize(label, NULL, true);
@ -3432,7 +3432,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format); DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format);
ImStrTrimBlanks(data_buf); ImStrTrimBlanks(data_buf);
ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoMarkEdited; ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited;
flags |= InputScalar_DefaultCharsFilter(data_type, format); flags |= InputScalar_DefaultCharsFilter(data_type, format);
bool value_changed = false; bool value_changed = false;
@ -3480,7 +3480,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
// Testing ActiveId as a minor optimization as filtering is not needed until active // Testing ActiveId as a minor optimization as filtering is not needed until active
if (g.ActiveId == 0 && (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0) if (g.ActiveId == 0 && (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0)
flags |= InputScalar_DefaultCharsFilter(data_type, format); flags |= InputScalar_DefaultCharsFilter(data_type, format);
flags |= ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string. flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
bool value_changed = false; bool value_changed = false;
if (p_step == NULL) if (p_step == NULL)
@ -4111,12 +4111,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
const bool RENDER_SELECTION_WHEN_INACTIVE = false; const bool RENDER_SELECTION_WHEN_INACTIVE = false;
const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0; const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0;
const bool is_readonly = (flags & ImGuiInputTextFlags_ReadOnly) != 0;
const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0;
const bool is_resizable = (flags & ImGuiInputTextFlags_CallbackResize) != 0;
if (is_resizable)
IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag!
if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope (including the scrollbar) if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope (including the scrollbar)
BeginGroup(); BeginGroup();
@ -4186,6 +4180,15 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// We are only allowed to access the state if we are already the active widget. // We are only allowed to access the state if we are already the active widget.
ImGuiInputTextState* state = GetInputTextState(id); ImGuiInputTextState* state = GetInputTextState(id);
if (g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly)
flags |= ImGuiInputTextFlags_ReadOnly;
const bool is_readonly = (flags & ImGuiInputTextFlags_ReadOnly) != 0;
const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0;
const bool is_resizable = (flags & ImGuiInputTextFlags_CallbackResize) != 0;
if (is_resizable)
IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag!
const bool input_requested_by_tabbing = (item_status_flags & ImGuiItemStatusFlags_FocusedByTabbing) != 0; const bool input_requested_by_tabbing = (item_status_flags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateId == id) && ((g.NavActivateFlags & ImGuiActivateFlags_PreferInput) || (g.NavInputSource == ImGuiInputSource_Keyboard))); const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateId == id) && ((g.NavActivateFlags & ImGuiActivateFlags_PreferInput) || (g.NavInputSource == ImGuiInputSource_Keyboard)));
@ -4722,7 +4725,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty) { state->Stb.select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb.select_start : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); } if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty) { state->Stb.select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb.select_start : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); }
if (buf_dirty) if (buf_dirty)
{ {
IM_ASSERT((flags & ImGuiInputTextFlags_ReadOnly) == 0); IM_ASSERT(!is_readonly);
IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text! IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
InputTextReconcileUndoStateAfterUserCallback(state, callback_data.Buf, callback_data.BufTextLen); // FIXME: Move the rest of this block inside function and rename to InputTextReconcileStateAfterUserCallback() ? InputTextReconcileUndoStateAfterUserCallback(state, callback_data.Buf, callback_data.BufTextLen); // FIXME: Move the rest of this block inside function and rename to InputTextReconcileStateAfterUserCallback() ?
if (callback_data.BufTextLen > backup_current_text_length && is_resizable) if (callback_data.BufTextLen > backup_current_text_length && is_resizable)
@ -5344,7 +5347,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
// Drag and Drop Target // Drag and Drop Target
// NB: The flag test is merely an optional micro-optimization, BeginDragDropTarget() does the same test. // NB: The flag test is merely an optional micro-optimization, BeginDragDropTarget() does the same test.
if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropTarget()) if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) && !(g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropTarget())
{ {
bool accepted_drag_drop = false; bool accepted_drag_drop = false;
if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
@ -5409,6 +5412,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
ImGuiIO& io = g.IO; ImGuiIO& io = g.IO;
const float width = CalcItemWidth(); const float width = CalcItemWidth();
const bool is_readonly = ((g.NextItemData.ItemFlags | g.CurrentItemFlags) & ImGuiItemFlags_ReadOnly) != 0;
g.NextItemData.ClearFlags(); g.NextItemData.ClearFlags();
PushID(label); PushID(label);
@ -5479,7 +5483,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
{ {
// Hue wheel + SV triangle logic // Hue wheel + SV triangle logic
InvisibleButton("hsv", ImVec2(sv_picker_size + style.ItemInnerSpacing.x + bars_width, sv_picker_size)); InvisibleButton("hsv", ImVec2(sv_picker_size + style.ItemInnerSpacing.x + bars_width, sv_picker_size));
if (IsItemActive()) if (IsItemActive() && !is_readonly)
{ {
ImVec2 initial_off = g.IO.MouseClickedPos[0] - wheel_center; ImVec2 initial_off = g.IO.MouseClickedPos[0] - wheel_center;
ImVec2 current_off = g.IO.MousePos - wheel_center; ImVec2 current_off = g.IO.MousePos - wheel_center;
@ -5514,7 +5518,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
{ {
// SV rectangle logic // SV rectangle logic
InvisibleButton("sv", ImVec2(sv_picker_size, sv_picker_size)); InvisibleButton("sv", ImVec2(sv_picker_size, sv_picker_size));
if (IsItemActive()) if (IsItemActive() && !is_readonly)
{ {
S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size - 1)); S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size - 1));
V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1)); V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1));
@ -5527,7 +5531,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
// Hue bar logic // Hue bar logic
SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y)); SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y));
InvisibleButton("hue", ImVec2(bars_width, sv_picker_size)); InvisibleButton("hue", ImVec2(bars_width, sv_picker_size));
if (IsItemActive()) if (IsItemActive() && !is_readonly)
{ {
H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1)); H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1));
value_changed = value_changed_h = true; value_changed = value_changed_h = true;
@ -6472,7 +6476,7 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFl
ImGuiID id = window->GetID(label); ImGuiID id = window->GetID(label);
flags |= ImGuiTreeNodeFlags_CollapsingHeader; flags |= ImGuiTreeNodeFlags_CollapsingHeader;
if (p_visible) if (p_visible)
flags |= ImGuiTreeNodeFlags_AllowOverlap | ImGuiTreeNodeFlags_ClipLabelForTrailingButton; flags |= ImGuiTreeNodeFlags_AllowOverlap | (ImGuiTreeNodeFlags)ImGuiTreeNodeFlags_ClipLabelForTrailingButton;
bool is_open = TreeNodeBehavior(id, flags, label); bool is_open = TreeNodeBehavior(id, flags, label);
if (p_visible != NULL) if (p_visible != NULL)
{ {
@ -7524,18 +7528,18 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
ImGuiWindow* child_menu_window = (child_popup && child_popup->Window && child_popup->Window->ParentWindow == window) ? child_popup->Window : NULL; ImGuiWindow* child_menu_window = (child_popup && child_popup->Window && child_popup->Window->ParentWindow == window) ? child_popup->Window : NULL;
if (g.HoveredWindow == window && child_menu_window != NULL) if (g.HoveredWindow == window && child_menu_window != NULL)
{ {
float ref_unit = g.FontSize; // FIXME-DPI const float ref_unit = g.FontSize; // FIXME-DPI
float child_dir = (window->Pos.x < child_menu_window->Pos.x) ? 1.0f : -1.0f; const float child_dir = (window->Pos.x < child_menu_window->Pos.x) ? 1.0f : -1.0f;
ImRect next_window_rect = child_menu_window->Rect(); const ImRect next_window_rect = child_menu_window->Rect();
ImVec2 ta = (g.IO.MousePos - g.IO.MouseDelta); ImVec2 ta = (g.IO.MousePos - g.IO.MouseDelta);
ImVec2 tb = (child_dir > 0.0f) ? next_window_rect.GetTL() : next_window_rect.GetTR(); ImVec2 tb = (child_dir > 0.0f) ? next_window_rect.GetTL() : next_window_rect.GetTR();
ImVec2 tc = (child_dir > 0.0f) ? next_window_rect.GetBL() : next_window_rect.GetBR(); ImVec2 tc = (child_dir > 0.0f) ? next_window_rect.GetBL() : next_window_rect.GetBR();
float extra = ImClamp(ImFabs(ta.x - tb.x) * 0.30f, ref_unit * 0.5f, ref_unit * 2.5f); // add a bit of extra slack. const float pad_farmost_h = ImClamp(ImFabs(ta.x - tb.x) * 0.30f, ref_unit * 0.5f, ref_unit * 2.5f); // Add a bit of extra slack.
ta.x += child_dir * -0.5f; ta.x += child_dir * -0.5f;
tb.x += child_dir * ref_unit; tb.x += child_dir * ref_unit;
tc.x += child_dir * ref_unit; tc.x += child_dir * ref_unit;
tb.y = ta.y + ImMax((tb.y - extra) - ta.y, -ref_unit * 8.0f); // triangle has maximum height to limit the slope and the bias toward large sub-menus tb.y = ta.y + ImMax((tb.y - pad_farmost_h) - ta.y, -ref_unit * 8.0f); // Triangle has maximum height to limit the slope and the bias toward large sub-menus
tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +ref_unit * 8.0f); tc.y = ta.y + ImMin((tc.y + pad_farmost_h) - ta.y, +ref_unit * 8.0f);
moving_toward_child_menu = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos); moving_toward_child_menu = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos);
//GetForegroundDrawList()->AddTriangleFilled(ta, tb, tc, moving_toward_child_menu ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); // [DEBUG] //GetForegroundDrawList()->AddTriangleFilled(ta, tb, tc, moving_toward_child_menu ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); // [DEBUG]
} }
@ -7547,10 +7551,13 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
want_close = true; want_close = true;
// Open // Open
// (note: at this point 'hovered' actually includes the NavDisableMouseHover == false test)
if (!menu_is_open && pressed) // Click/activate to open if (!menu_is_open && pressed) // Click/activate to open
want_open = true; want_open = true;
else if (!menu_is_open && hovered && !moving_toward_child_menu) // Hover to open else if (!menu_is_open && hovered && !moving_toward_child_menu) // Hover to open
want_open = true; want_open = true;
else if (!menu_is_open && hovered && g.HoveredIdTimer >= 0.30f && g.MouseStationaryTimer >= 0.30f) // Hover to open (timer fallback)
want_open = true;
if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open
{ {
want_open = true; want_open = true;

Loading…
Cancel
Save