mirror of
https://github.com/ocornut/imgui.git
synced 2025-01-18 17:24:09 +01:00
Merge branch 'master' into docking
# Conflicts: # backends/imgui_impl_glfw.cpp # backends/imgui_impl_win32.cpp
This commit is contained in:
commit
5ea96c15cd
@ -24,6 +24,8 @@
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||
// 2024-07-08: *BREAKING* Renamed ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback to ImGui_ImplGlfw_InstallEmscriptenCallbacks(), added GLFWWindow* parameter.
|
||||
// 2024-07-08: Emscripten: Added support for GLFW3 contrib port (GLFW 3.4.0 features + bug fixes): to enable, replace -sUSE_GLFW=3 with --use-port=contrib.glfw3 (requires emscripten 3.1.59+) (https://github.com/pongasoft/emscripten-glfw)
|
||||
// 2024-07-02: Emscripten: Added io.PlatformOpenInShellFn() handler for Emscripten versions.
|
||||
// 2023-12-19: Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to register canvas selector and auto-resize GLFW window.
|
||||
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys.
|
||||
@ -106,6 +108,11 @@
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
#ifdef EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3
|
||||
#include <GLFW/emscripten_glfw3.h>
|
||||
#else
|
||||
#define EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// We gather version tests as define in order to easily see which features are version-dependent.
|
||||
@ -157,7 +164,7 @@ struct ImGui_ImplGlfw_Data
|
||||
bool InstalledCallbacks;
|
||||
bool CallbacksChainForAllWindows;
|
||||
bool WantUpdateMonitors;
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||
const char* CanvasSelector;
|
||||
#endif
|
||||
|
||||
@ -366,7 +373,7 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo
|
||||
if (bd->PrevUserCallbackScroll != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
||||
bd->PrevUserCallbackScroll(window, xoffset, yoffset);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||
// Ignore GLFW events: will be processed in ImGui_ImplEmscripten_WheelCallback().
|
||||
return;
|
||||
#endif
|
||||
@ -377,7 +384,7 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo
|
||||
|
||||
static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
|
||||
{
|
||||
#if GLFW_HAS_GETKEYNAME && !defined(__EMSCRIPTEN__)
|
||||
#if GLFW_HAS_GETKEYNAME && !defined(EMSCRIPTEN_USE_EMBEDDED_GLFW3)
|
||||
// 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)
|
||||
// See https://github.com/glfw/glfw/issues/1502 for details.
|
||||
@ -388,7 +395,7 @@ static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
|
||||
GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr);
|
||||
const char* key_name = glfwGetKeyName(key, scancode);
|
||||
glfwSetErrorCallback(prev_error_callback);
|
||||
#if GLFW_HAS_GETERROR && !defined(__EMSCRIPTEN__) // Eat errors (see #5908)
|
||||
#if GLFW_HAS_GETERROR && !defined(EMSCRIPTEN_USE_EMBEDDED_GLFW3) // Eat errors (see #5908)
|
||||
(void)glfwGetError(nullptr);
|
||||
#endif
|
||||
if (key_name && key_name[0] != 0 && key_name[1] == 0)
|
||||
@ -496,7 +503,7 @@ void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int)
|
||||
bd->WantUpdateMonitors = true;
|
||||
}
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||
static EM_BOOL ImGui_ImplEmscripten_WheelCallback(int, const EmscriptenWheelEvent* ev, void*)
|
||||
{
|
||||
// Mimic Emscripten_HandleWheel() in SDL.
|
||||
@ -634,12 +641,6 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||
// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
|
||||
if (install_callbacks)
|
||||
ImGui_ImplGlfw_InstallCallbacks(window);
|
||||
// Register Emscripten Wheel callback to workaround issue in Emscripten GLFW Emulation (#6096)
|
||||
// We intentionally do not check 'if (install_callbacks)' here, as some users may set it to false and call GLFW callback themselves.
|
||||
// FIXME: May break chaining in case user registered their own Emscripten callback?
|
||||
#ifdef __EMSCRIPTEN__
|
||||
emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, ImGui_ImplEmscripten_WheelCallback);
|
||||
#endif
|
||||
|
||||
// Update monitors the first time (note: monitor callback are broken in GLFW 3.2 and earlier, see github.com/glfw/glfw/issues/784)
|
||||
ImGui_ImplGlfw_UpdateMonitors();
|
||||
@ -694,8 +695,9 @@ void ImGui_ImplGlfw_Shutdown()
|
||||
|
||||
if (bd->InstalledCallbacks)
|
||||
ImGui_ImplGlfw_RestoreCallbacks(bd->Window);
|
||||
#ifdef __EMSCRIPTEN__
|
||||
emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, nullptr);
|
||||
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||
if (bd->CanvasSelector)
|
||||
emscripten_set_wheel_callback(bd->CanvasSelector, nullptr, false, nullptr);
|
||||
#endif
|
||||
|
||||
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
||||
@ -727,7 +729,7 @@ static void ImGui_ImplGlfw_UpdateMouseData()
|
||||
ImGuiViewport* viewport = platform_io.Viewports[n];
|
||||
GLFWwindow* window = (GLFWwindow*)viewport->PlatformHandle;
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||
const bool is_window_focused = true;
|
||||
#else
|
||||
const bool is_window_focused = glfwGetWindowAttrib(window, GLFW_FOCUSED) != 0;
|
||||
@ -821,7 +823,7 @@ static void ImGui_ImplGlfw_UpdateGamepads()
|
||||
return;
|
||||
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||
#if GLFW_HAS_GAMEPAD_API && !defined(__EMSCRIPTEN__)
|
||||
#if GLFW_HAS_GAMEPAD_API && !defined(EMSCRIPTEN_USE_EMBEDDED_GLFW3)
|
||||
GLFWgamepadstate gamepad;
|
||||
if (!glfwGetGamepadState(GLFW_JOYSTICK_1, &gamepad))
|
||||
return;
|
||||
@ -939,7 +941,7 @@ void ImGui_ImplGlfw_NewFrame()
|
||||
ImGui_ImplGlfw_UpdateGamepads();
|
||||
}
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||
static EM_BOOL ImGui_ImplGlfw_OnCanvasSizeChange(int event_type, const EmscriptenUiEvent* event, void* user_data)
|
||||
{
|
||||
ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data;
|
||||
@ -960,7 +962,7 @@ static EM_BOOL ImGui_ImplEmscripten_FullscreenChangeCallback(int event_type, con
|
||||
|
||||
// 'canvas_selector' is a CSS selector. The event listener is applied to the first element that matches the query.
|
||||
// STRING MUST PERSIST FOR THE APPLICATION DURATION. PLEASE USE A STRING LITERAL OR ENSURE POINTER WILL STAY VALID.
|
||||
void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector)
|
||||
void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow*, const char* canvas_selector)
|
||||
{
|
||||
IM_ASSERT(canvas_selector != nullptr);
|
||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
||||
@ -972,8 +974,24 @@ void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_sel
|
||||
|
||||
// Change the size of the GLFW window according to the size of the canvas
|
||||
ImGui_ImplGlfw_OnCanvasSizeChange(EMSCRIPTEN_EVENT_RESIZE, {}, bd);
|
||||
|
||||
// Register Emscripten Wheel callback to workaround issue in Emscripten GLFW Emulation (#6096)
|
||||
// We intentionally do not check 'if (install_callbacks)' here, as some users may set it to false and call GLFW callback themselves.
|
||||
// FIXME: May break chaining in case user registered their own Emscripten callback?
|
||||
emscripten_set_wheel_callback(bd->CanvasSelector, nullptr, false, ImGui_ImplEmscripten_WheelCallback);
|
||||
}
|
||||
#endif
|
||||
#elif defined(EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3)
|
||||
// When using --use-port=contrib.glfw3 for the GLFW implementation, you can override the behavior of this call
|
||||
// by invoking emscripten_glfw_make_canvas_resizable afterward.
|
||||
// See https://github.com/pongasoft/emscripten-glfw/blob/master/docs/Usage.md#how-to-make-the-canvas-resizable-by-the-user for an explanation
|
||||
void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* window, const char* canvas_selector)
|
||||
{
|
||||
GLFWwindow* w = (GLFWwindow*)(EM_ASM_INT({ return Module.glfwGetWindow(UTF8ToString($0)); }, canvas_selector));
|
||||
IM_ASSERT(window == w); // Sanity check
|
||||
IM_UNUSED(w);
|
||||
emscripten_glfw_make_canvas_resizable(window, "window", nullptr);
|
||||
}
|
||||
#endif // #ifdef EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
|
@ -34,9 +34,10 @@ IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool ins
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
|
||||
|
||||
// Emscripten related initialization phase methods
|
||||
// Emscripten related initialization phase methods (call after ImGui_ImplGlfw_InitForOpenGL)
|
||||
#ifdef __EMSCRIPTEN__
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* window, const char* canvas_selector);
|
||||
//static inline void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector) { ImGui_ImplGlfw_InstallEmscriptenCallbacks(nullptr, canvas_selector); } } // Renamed in 1.91.0
|
||||
#endif
|
||||
|
||||
// GLFW callbacks install
|
||||
|
@ -429,10 +429,10 @@ static void ImGui_ImplSDL3_SetupPlatformHandles(ImGuiViewport* viewport, SDL_Win
|
||||
{
|
||||
viewport->PlatformHandle = window;
|
||||
viewport->PlatformHandleRaw = nullptr;
|
||||
#if defined(__WIN32__) && !defined(__WINRT__)
|
||||
viewport->PlatformHandleRaw = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.win32.hwnd", nullptr);
|
||||
#if defined(_WIN32) && !defined(__WINRT__)
|
||||
viewport->PlatformHandleRaw = (HWND)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr);
|
||||
#elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA)
|
||||
viewport->PlatformHandleRaw = (void*)SDL_GetProperty(SDL_GetWindowProperties(window), "SDL.window.cocoa.window", nullptr);
|
||||
viewport->PlatformHandleRaw = SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -924,7 +924,7 @@ static void ImGui_ImplSDL3_DestroyWindow(ImGuiViewport* viewport)
|
||||
if (ImGui_ImplSDL3_ViewportData* vd = (ImGui_ImplSDL3_ViewportData*)viewport->PlatformUserData)
|
||||
{
|
||||
if (vd->GLContext && vd->WindowOwned)
|
||||
SDL_GL_DeleteContext(vd->GLContext);
|
||||
SDL_GL_DestroyContext(vd->GLContext);
|
||||
if (vd->Window && vd->WindowOwned)
|
||||
SDL_DestroyWindow(vd->Window);
|
||||
vd->GLContext = nullptr;
|
||||
|
@ -23,6 +23,7 @@
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||
// 2024-07-08: Inputs: Fixed ImGuiMod_Super being mapped to VK_APPS instead of VK_LWIN||VK_RWIN. (#7768)
|
||||
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys.
|
||||
// 2023-09-25: Inputs: Synthesize key-down event on key-up for VK_SNAPSHOT / ImGuiKey_PrintScreen as Windows doesn't emit it (same behavior as GLFW/SDL).
|
||||
// 2023-09-07: Inputs: Added support for keyboard codepage conversion for when application is compiled in MBCS mode and using a non-Unicode window.
|
||||
@ -308,7 +309,7 @@ static void ImGui_ImplWin32_UpdateKeyModifiers()
|
||||
io.AddKeyEvent(ImGuiMod_Ctrl, IsVkDown(VK_CONTROL));
|
||||
io.AddKeyEvent(ImGuiMod_Shift, IsVkDown(VK_SHIFT));
|
||||
io.AddKeyEvent(ImGuiMod_Alt, IsVkDown(VK_MENU));
|
||||
io.AddKeyEvent(ImGuiMod_Super, IsVkDown(VK_APPS));
|
||||
io.AddKeyEvent(ImGuiMod_Super, IsVkDown(VK_LWIN) || IsVkDown(VK_RWIN));
|
||||
}
|
||||
|
||||
// This code supports multi-viewports (multiple OS Windows mapped into different Dear ImGui viewports)
|
||||
|
@ -49,6 +49,8 @@ Breaking changes:
|
||||
- Commented out obsolete ImGuiModFlags (renamed to ImGuiKeyChord in 1.89). (#4921, #456)
|
||||
- Commented out obsolete ImGuiModFlags_XXX values (renamed to ImGuiMod_XXX in 1.89). (#4921, #456)
|
||||
- ImGuiModFlags_Ctrl -> ImGuiMod_Ctrl, ImGuiModFlags_Shift -> ImGuiMod_Shift etc.
|
||||
- Backends: GLFW+Emscripten: Renamed ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to
|
||||
ImGui_ImplGlfw_InstallEmscriptenCallbacks(), with additional GLFWWindow* parameter. (#7647) [@ypujante]
|
||||
|
||||
Other changes:
|
||||
|
||||
@ -60,9 +62,19 @@ Other changes:
|
||||
Debug log entries add a imgui frame counter prefix + are redirected to ShowDebugLogWindow() and
|
||||
other configurable locations. Always call IMGUI_DEBUG_LOG() for maximum stripping in caller code.
|
||||
- Debug Tools: Debug Log: Added "Configure Outputs.." button. (#5855)
|
||||
- Backends: Win32: Fixed ImGuiMod_Super being mapped to VK_APPS instead of VK_LWIN||VK_RWIN.
|
||||
(#7768, #4858, #2622) [@Aemony]
|
||||
- Backends: SDL3: Update for API changes: SDLK_x renames and SDLK_KP_x removals (#7761, #7762)
|
||||
- Backends: SDL3: Update for API changes: SDL_GetProperty() change to SDL_GetPointerProperty(). (#7794) [@wermipls]
|
||||
- Backends: SDL2,SDL3,OSX: Update for io.SetPlatformImeDataFn() -> io.PlatformSetImeDataFn() rename.
|
||||
- Backends: GLFW,SDL2: Added ioPlatformOpenInShellFn handler for web/Emscripten versions. (#7660)
|
||||
- Backends: GLFW,SDL2: Added io.PlatformOpenInShellFn handler for web/Emscripten versions. (#7660)
|
||||
[@ypujante, @ocornut]
|
||||
- Backends; GLFW+Emscripten: Added support for GLFW3 contrib port which fixes many of the things
|
||||
not supported by the embedded GLFW: gamepad support, mouse cursor shapes, copy to clipboard,
|
||||
workaround for Super/Meta key, different ways of resizing, multi-window (glfw/canvas) support.
|
||||
(#7647) [@ypujante]
|
||||
- Backends: GLFW+Emscripten: Fixed Emscripten warning when using mouse wheel on some setups
|
||||
"Unable to preventDefault inside passive event listener". (#7647, #7600) [@ypujante]
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
@ -97,7 +97,7 @@ int main(int, char**)
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
#ifdef __EMSCRIPTEN__
|
||||
ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback("#canvas");
|
||||
ImGui_ImplGlfw_InstallEmscriptenCallbacks(window, "#canvas");
|
||||
#endif
|
||||
ImGui_ImplOpenGL3_Init(glsl_version);
|
||||
|
||||
|
@ -27,6 +27,12 @@ set(IMGUI_DIR ../../)
|
||||
|
||||
# Libraries
|
||||
if(EMSCRIPTEN)
|
||||
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "3.1.57")
|
||||
set(IMGUI_EMSCRIPTEN_GLFW3 "--use-port=contrib.glfw3" CACHE STRING "Choose between --use-port=contrib.glfw3 and -sUSE_GLFW=3 for GLFW implementation (default to --use-port=contrib.glfw3)")
|
||||
else()
|
||||
# cannot use contrib.glfw3 prior to 3.1.57
|
||||
set(IMGUI_EMSCRIPTEN_GLFW3 "-sUSE_GLFW=3" CACHE STRING "Use -sUSE_GLFW=3 for GLFW implementation" FORCE)
|
||||
endif()
|
||||
set(LIBRARIES glfw)
|
||||
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
|
||||
else()
|
||||
@ -82,9 +88,16 @@ target_link_libraries(example_glfw_wgpu PUBLIC ${LIBRARIES})
|
||||
|
||||
# Emscripten settings
|
||||
if(EMSCRIPTEN)
|
||||
if("${IMGUI_EMSCRIPTEN_GLFW3}" STREQUAL "--use-port=contrib.glfw3")
|
||||
target_compile_options(example_glfw_wgpu PUBLIC
|
||||
"${IMGUI_EMSCRIPTEN_GLFW3}"
|
||||
"-DEMSCRIPTEN_USE_PORT_CONTRIB_GLFW3" # unnecessary beyond emscripten 3.1.59
|
||||
)
|
||||
endif()
|
||||
message(STATUS "Using ${IMGUI_EMSCRIPTEN_GLFW3} GLFW implementation")
|
||||
target_link_options(example_glfw_wgpu PRIVATE
|
||||
"-sUSE_WEBGPU=1"
|
||||
"-sUSE_GLFW=3"
|
||||
"${IMGUI_EMSCRIPTEN_GLFW3}"
|
||||
"-sWASM=1"
|
||||
"-sALLOW_MEMORY_GROWTH=1"
|
||||
"-sNO_EXIT_RUNTIME=0"
|
||||
|
@ -102,7 +102,7 @@ int main(int, char**)
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplGlfw_InitForOther(window, true);
|
||||
#ifdef __EMSCRIPTEN__
|
||||
ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback("#canvas");
|
||||
ImGui_ImplGlfw_InstallEmscriptenCallbacks(window, "#canvas");
|
||||
#endif
|
||||
ImGui_ImplWGPU_InitInfo init_info;
|
||||
init_info.Device = wgpu_device;
|
||||
|
@ -221,7 +221,7 @@ int main(int, char**)
|
||||
ImGui_ImplSDL3_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
SDL_GL_DeleteContext(gl_context);
|
||||
SDL_GL_DestroyContext(gl_context);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
|
||||
|
49
imgui.cpp
49
imgui.cpp
@ -2115,6 +2115,10 @@ void ImFormatStringToTempBuffer(const char** out_buf, const char** out_buf_end,
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// FIXME: Should rework API toward allowing multiple in-flight temp buffers (easier and safer for caller)
|
||||
// by making the caller acquire a temp buffer token, with either explicit or destructor release, e.g.
|
||||
// ImGuiTempBufferToken token;
|
||||
// ImFormatStringToTempBuffer(token, ...);
|
||||
void ImFormatStringToTempBufferV(const char** out_buf, const char** out_buf_end, const char* fmt, va_list args)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@ -3876,7 +3880,7 @@ void ImGui::Shutdown()
|
||||
g.FontStack.clear();
|
||||
g.OpenPopupStack.clear();
|
||||
g.BeginPopupStack.clear();
|
||||
g.NavTreeNodeStack.clear();
|
||||
g.TreeNodeStack.clear();
|
||||
|
||||
g.CurrentViewport = g.MouseViewport = g.MouseLastHoveredViewport = NULL;
|
||||
g.Viewports.clear_delete();
|
||||
@ -7627,7 +7631,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
window->DC.MenuBarAppending = false;
|
||||
window->DC.MenuColumns.Update(style.ItemSpacing.x, window_just_activated_by_user);
|
||||
window->DC.TreeDepth = 0;
|
||||
window->DC.TreeJumpToParentOnPopMask = 0x00;
|
||||
window->DC.TreeHasStackDataDepthMask = 0x00;
|
||||
window->DC.ChildWindows.resize(0);
|
||||
window->DC.StateStorage = &window->StateStorage;
|
||||
window->DC.CurrentColumns = NULL;
|
||||
@ -12722,7 +12726,7 @@ void ImGui::NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result)
|
||||
}
|
||||
|
||||
// Called by TreePop() to implement ImGuiTreeNodeFlags_NavLeftJumpsBackHere
|
||||
void ImGui::NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiNavTreeNodeData* tree_node_data)
|
||||
void ImGui::NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiTreeNodeStackData* tree_node_data)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
g.NavMoveScoringItems = false;
|
||||
@ -19973,11 +19977,18 @@ static void SetClipboardTextFn_DefaultImpl(void* user_data_ctx, const char* text
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if defined(__APPLE__) && defined(TARGET_OS_IPHONE) && !defined(IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS)
|
||||
#ifndef IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS
|
||||
#if defined(__APPLE__) && TARGET_OS_IPHONE
|
||||
#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS)
|
||||
#if defined(_WIN32) && defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
|
||||
#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS
|
||||
#ifdef _WIN32
|
||||
#include <shellapi.h> // ShellExecuteA()
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "shell32")
|
||||
@ -19986,18 +19997,32 @@ static bool PlatformOpenInShellFn_DefaultImpl(ImGuiContext*, const char* path)
|
||||
{
|
||||
return (INT_PTR)::ShellExecuteA(NULL, "open", path, NULL, NULL, SW_SHOWDEFAULT) > 32;
|
||||
}
|
||||
#elif !defined(IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS)
|
||||
#else
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
static bool PlatformOpenInShellFn_DefaultImpl(ImGuiContext*, const char* path)
|
||||
{
|
||||
#if __APPLE__
|
||||
const char* open_executable = "open";
|
||||
#if defined(__APPLE__)
|
||||
const char* args[] { "open", "--", path, NULL };
|
||||
#else
|
||||
const char* open_executable = "xdg-open";
|
||||
const char* args[] { "xdg-open", path, NULL };
|
||||
#endif
|
||||
ImGuiTextBuffer buf;
|
||||
buf.appendf("%s \"%s\"", open_executable, path);
|
||||
return system(buf.c_str()) != -1;
|
||||
pid_t pid = fork();
|
||||
if (pid < 0)
|
||||
return false;
|
||||
if (!pid)
|
||||
{
|
||||
execvp(args[0], const_cast<char **>(args));
|
||||
exit(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
return WEXITSTATUS(status) == 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
static bool PlatformOpenInShellFn_DefaultImpl(ImGuiContext*, const char*) { return false; }
|
||||
#endif // Default shell handlers
|
||||
|
@ -1013,6 +1013,7 @@ static void ShowDemoWindowWidgets()
|
||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &base_flags, ImGuiTreeNodeFlags_SpanAllColumns); ImGui::SameLine(); HelpMarker("For use in Tables only.");
|
||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_AllowOverlap", &base_flags, ImGuiTreeNodeFlags_AllowOverlap);
|
||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_Framed", &base_flags, ImGuiTreeNodeFlags_Framed); ImGui::SameLine(); HelpMarker("Draw frame with background (e.g. for CollapsingHeader)");
|
||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_NavLeftJumpsBackHere", &base_flags, ImGuiTreeNodeFlags_NavLeftJumpsBackHere);
|
||||
ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position);
|
||||
ImGui::Checkbox("Test tree node as drag source", &test_drag_and_drop);
|
||||
ImGui::Text("Hello!");
|
||||
@ -1045,7 +1046,7 @@ static void ShowDemoWindowWidgets()
|
||||
ImGui::Text("This is a drag and drop source");
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
if (i == 2)
|
||||
if (i == 2 && (base_flags & ImGuiTreeNodeFlags_SpanTextWidth))
|
||||
{
|
||||
// Item 2 has an additional inline button to help demonstrate SpanTextWidth.
|
||||
ImGui::SameLine();
|
||||
@ -1054,6 +1055,8 @@ static void ShowDemoWindowWidgets()
|
||||
if (node_open)
|
||||
{
|
||||
ImGui::BulletText("Blah blah\nBlah Blah");
|
||||
ImGui::SameLine();
|
||||
ImGui::SmallButton("Button");
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
@ -4293,7 +4296,7 @@ static void ShowDemoWindowTables()
|
||||
PushStyleCompact();
|
||||
ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg);
|
||||
ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags, ImGuiTableFlags_Borders);
|
||||
ImGui::SameLine(); HelpMarker("ImGuiTableFlags_Borders\n = ImGuiTableFlags_BordersInnerV\n | ImGuiTableFlags_BordersOuterV\n | ImGuiTableFlags_BordersInnerV\n | ImGuiTableFlags_BordersOuterH");
|
||||
ImGui::SameLine(); HelpMarker("ImGuiTableFlags_Borders\n = ImGuiTableFlags_BordersInnerV\n | ImGuiTableFlags_BordersOuterV\n | ImGuiTableFlags_BordersInnerH\n | ImGuiTableFlags_BordersOuterH");
|
||||
ImGui::Indent();
|
||||
|
||||
ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags, ImGuiTableFlags_BordersH);
|
||||
@ -7854,7 +7857,7 @@ static void ShowPlaceholderObject(const char* prefix, int uid)
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::AlignTextToFramePadding();
|
||||
bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
|
||||
bool node_open = ImGui::TreeNode("##Object", "%s_%u", prefix, uid);
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
ImGui::Text("my sailor is rich");
|
||||
|
||||
|
@ -140,7 +140,6 @@ struct ImGuiLastItemData; // Status storage for last submitted items
|
||||
struct ImGuiLocEntry; // A localization entry.
|
||||
struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only
|
||||
struct ImGuiNavItemData; // Result of a gamepad/keyboard directional navigation move query result
|
||||
struct ImGuiNavTreeNodeData; // Temporary storage for last TreeNode() being a Left arrow landing candidate.
|
||||
struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions
|
||||
struct ImGuiNextWindowData; // Storage for SetNextWindow** functions
|
||||
struct ImGuiNextItemData; // Storage for SetNextItem** functions
|
||||
@ -159,6 +158,7 @@ struct ImGuiTableInstanceData; // Storage for one instance of a same table
|
||||
struct ImGuiTableTempData; // Temporary storage for one table (one per table in the stack), shared between tables.
|
||||
struct ImGuiTableSettings; // Storage for a table .ini settings
|
||||
struct ImGuiTableColumnsSettings; // Storage for a column .ini settings
|
||||
struct ImGuiTreeNodeStackData; // Temporary storage for TreeNode().
|
||||
struct ImGuiTypingSelectState; // Storage for GetTypingSelectRequest()
|
||||
struct ImGuiTypingSelectRequest; // Storage for GetTypingSelectRequest() (aimed to be public)
|
||||
struct ImGuiWindow; // Storage for one window
|
||||
@ -977,8 +977,8 @@ enum ImGuiSelectableFlagsPrivate_
|
||||
// Extend ImGuiTreeNodeFlags_
|
||||
enum ImGuiTreeNodeFlagsPrivate_
|
||||
{
|
||||
ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 20,
|
||||
ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 21,// (FIXME-WIP) Turn Down arrow into an Up arrow, but reversed trees (#6517)
|
||||
ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 28,// FIXME-WIP: Hard-coded for CollapsingHeader()
|
||||
ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 29,// FIXME-WIP: Turn Down arrow into an Up arrow, but reversed trees (#6517)
|
||||
};
|
||||
|
||||
enum ImGuiSeparatorFlags_
|
||||
@ -1271,14 +1271,16 @@ struct ImGuiLastItemData
|
||||
ImGuiLastItemData() { memset(this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Store data emitted by TreeNode() for usage by TreePop() to implement ImGuiTreeNodeFlags_NavLeftJumpsBackHere.
|
||||
// This is the minimum amount of data that we need to perform the equivalent of NavApplyItemToResult() and which we can't infer in TreePop()
|
||||
// Only stored when the node is a potential candidate for landing on a Left arrow jump.
|
||||
struct ImGuiNavTreeNodeData
|
||||
// Store data emitted by TreeNode() for usage by TreePop()
|
||||
// - To implement ImGuiTreeNodeFlags_NavLeftJumpsBackHere: store the minimum amount of data
|
||||
// which we can't infer in TreePop(), to perform the equivalent of NavApplyItemToResult().
|
||||
// Only stored when the node is a potential candidate for landing on a Left arrow jump.
|
||||
struct ImGuiTreeNodeStackData
|
||||
{
|
||||
ImGuiID ID;
|
||||
ImGuiItemFlags InFlags;
|
||||
ImRect NavRect;
|
||||
ImGuiTreeNodeFlags TreeFlags;
|
||||
ImGuiItemFlags InFlags; // Used for nav landing
|
||||
ImRect NavRect; // Used for nav landing
|
||||
};
|
||||
|
||||
struct IMGUI_API ImGuiStackSizes
|
||||
@ -2234,7 +2236,7 @@ struct ImGuiContext
|
||||
ImVector<ImGuiGroupData> GroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin()
|
||||
ImVector<ImGuiPopupData> OpenPopupStack; // Which popups are open (persistent)
|
||||
ImVector<ImGuiPopupData> BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame)
|
||||
ImVector<ImGuiNavTreeNodeData> NavTreeNodeStack; // Stack for TreeNode() when a NavLeft requested is emitted.
|
||||
ImVector<ImGuiTreeNodeStackData>TreeNodeStack; // Stack for TreeNode()
|
||||
|
||||
// Viewports
|
||||
ImVector<ImGuiViewportP*> Viewports; // Active viewports (always 1+, and generally 1 unless multi-viewports are enabled). Each viewports hold their copy of ImDrawData.
|
||||
@ -2726,7 +2728,7 @@ struct IMGUI_API ImGuiWindowTempData
|
||||
ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs.
|
||||
ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items measurement
|
||||
int TreeDepth; // Current tree depth.
|
||||
ImU32 TreeJumpToParentOnPopMask; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31.. Could be turned into a ImU64 if necessary.
|
||||
ImU32 TreeHasStackDataDepthMask; // Store whether given depth has ImGuiTreeNodeStackData data. Could be turned into a ImU64 if necessary.
|
||||
ImVector<ImGuiWindow*> ChildWindows;
|
||||
ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state)
|
||||
ImGuiOldColumns* CurrentColumns; // Current columns set
|
||||
@ -3454,7 +3456,7 @@ namespace ImGui
|
||||
IMGUI_API void NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
|
||||
IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
|
||||
IMGUI_API void NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result);
|
||||
IMGUI_API void NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiNavTreeNodeData* tree_node_data);
|
||||
IMGUI_API void NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiTreeNodeStackData* tree_node_data);
|
||||
IMGUI_API void NavMoveRequestCancel();
|
||||
IMGUI_API void NavMoveRequestApplyResult();
|
||||
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
|
||||
|
@ -6317,6 +6317,21 @@ bool ImGui::TreeNodeUpdateNextOpen(ImGuiID id, ImGuiTreeNodeFlags flags)
|
||||
return is_open;
|
||||
}
|
||||
|
||||
// Store ImGuiTreeNodeStackData for just submitted node.
|
||||
static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
g.TreeNodeStack.resize(g.TreeNodeStack.Size + 1);
|
||||
ImGuiTreeNodeStackData* tree_node_data = &g.TreeNodeStack.back();
|
||||
tree_node_data->ID = g.LastItemData.ID;
|
||||
tree_node_data->TreeFlags = flags;
|
||||
tree_node_data->InFlags = g.LastItemData.InFlags;
|
||||
tree_node_data->NavRect = g.LastItemData.NavRect;
|
||||
window->DC.TreeHasStackDataDepthMask |= (1 << window->DC.TreeDepth);
|
||||
}
|
||||
|
||||
bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
@ -6386,20 +6401,19 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
// For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop().
|
||||
// It will become tempting to enable ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default or move it to ImGuiStyle.
|
||||
// Currently only supports 32 level deep and we are fine with (1 << Depth) overflowing into a zero, easy to increase.
|
||||
if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
||||
if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
|
||||
{
|
||||
g.NavTreeNodeStack.resize(g.NavTreeNodeStack.Size + 1);
|
||||
ImGuiNavTreeNodeData* nav_tree_node_data = &g.NavTreeNodeStack.back();
|
||||
nav_tree_node_data->ID = id;
|
||||
nav_tree_node_data->InFlags = g.LastItemData.InFlags;
|
||||
nav_tree_node_data->NavRect = g.LastItemData.NavRect;
|
||||
window->DC.TreeJumpToParentOnPopMask |= (1 << window->DC.TreeDepth);
|
||||
}
|
||||
bool store_tree_node_stack_data = false;
|
||||
if (!(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
||||
{
|
||||
if ((flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && is_open && !g.NavIdIsAlive)
|
||||
if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
|
||||
store_tree_node_stack_data = true;
|
||||
}
|
||||
|
||||
const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
|
||||
if (!item_add)
|
||||
{
|
||||
if (store_tree_node_stack_data && is_open)
|
||||
TreeNodeStoreStackData(flags); // Call before TreePushOverrideID()
|
||||
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
||||
TreePushOverrideID(id);
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
|
||||
@ -6540,8 +6554,11 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
else
|
||||
RenderText(text_pos, label, label_end, false);
|
||||
|
||||
if (store_tree_node_stack_data && is_open)
|
||||
TreeNodeStoreStackData(flags); // Call before TreePushOverrideID()
|
||||
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
||||
TreePushOverrideID(id);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
|
||||
return is_open;
|
||||
}
|
||||
@ -6580,16 +6597,19 @@ void ImGui::TreePop()
|
||||
window->DC.TreeDepth--;
|
||||
ImU32 tree_depth_mask = (1 << window->DC.TreeDepth);
|
||||
|
||||
// Handle Left arrow to move to parent tree node (when ImGuiTreeNodeFlags_NavLeftJumpsBackHere is enabled)
|
||||
if (window->DC.TreeJumpToParentOnPopMask & tree_depth_mask) // Only set during request
|
||||
if (window->DC.TreeHasStackDataDepthMask & tree_depth_mask) // Only set during request
|
||||
{
|
||||
ImGuiNavTreeNodeData* nav_tree_node_data = &g.NavTreeNodeStack.back();
|
||||
IM_ASSERT(nav_tree_node_data->ID == window->IDStack.back());
|
||||
if (g.NavIdIsAlive && g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
|
||||
NavMoveRequestResolveWithPastTreeNode(&g.NavMoveResultLocal, nav_tree_node_data);
|
||||
g.NavTreeNodeStack.pop_back();
|
||||
ImGuiTreeNodeStackData* data = &g.TreeNodeStack.back();
|
||||
IM_ASSERT(data->ID == window->IDStack.back());
|
||||
if (data->TreeFlags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere)
|
||||
{
|
||||
// Handle Left arrow to move to parent tree node (when ImGuiTreeNodeFlags_NavLeftJumpsBackHere is enabled)
|
||||
if (g.NavIdIsAlive && g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
|
||||
NavMoveRequestResolveWithPastTreeNode(&g.NavMoveResultLocal, data);
|
||||
}
|
||||
g.TreeNodeStack.pop_back();
|
||||
window->DC.TreeHasStackDataDepthMask &= ~tree_depth_mask;
|
||||
}
|
||||
window->DC.TreeJumpToParentOnPopMask &= tree_depth_mask - 1;
|
||||
|
||||
IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much.
|
||||
PopID();
|
||||
|
Loading…
x
Reference in New Issue
Block a user