From 2889a14f86823c4b39b6e4d070fef19064167ab2 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 21 Dec 2018 16:45:24 +0100 Subject: [PATCH 01/14] Build fix for master. --- examples/imgui_impl_sdl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/imgui_impl_sdl.cpp b/examples/imgui_impl_sdl.cpp index 28253db0..730bce80 100644 --- a/examples/imgui_impl_sdl.cpp +++ b/examples/imgui_impl_sdl.cpp @@ -224,7 +224,7 @@ static void ImGui_ImplSDL2_UpdateMousePosAndButtons() io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; -#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS)) +#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) SDL_Window* focused_window = SDL_GetKeyboardFocus(); if (g_Window == focused_window) { From a71d3c8cb367469eaaffb8855ce5979f45df4fde Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 21 Dec 2018 18:40:16 +0100 Subject: [PATCH 02/14] Viewport: Misc comments following user feedbacks.. --- examples/example_glfw_opengl2/main.cpp | 5 ++++- examples/example_glfw_opengl3/main.cpp | 5 ++++- examples/example_sdl_opengl2/main.cpp | 6 +++++- examples/example_sdl_opengl3/main.cpp | 6 +++++- imgui.cpp | 8 ++++---- imgui_internal.h | 1 + 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/examples/example_glfw_opengl2/main.cpp b/examples/example_glfw_opengl2/main.cpp index 5b0c9023..a3ffcb30 100644 --- a/examples/example_glfw_opengl2/main.cpp +++ b/examples/example_glfw_opengl2/main.cpp @@ -144,11 +144,14 @@ int main(int, char**) ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData()); // Update and Render additional Platform Windows + // (Platform functions may change the current OpenGL context, so we save/restore it to make it easier to paste this code elsewhere. + // For this specific demo app we could also call glfwMakeContextCurrent(window) directly) if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + GLFWwindow* backup_current_context = glfwGetCurrentContext(); ImGui::UpdatePlatformWindows(); ImGui::RenderPlatformWindowsDefault(); - glfwMakeContextCurrent(window); + glfwMakeContextCurrent(backup_current_context); } glfwSwapBuffers(window); diff --git a/examples/example_glfw_opengl3/main.cpp b/examples/example_glfw_opengl3/main.cpp index 4268a210..f5dd65f0 100644 --- a/examples/example_glfw_opengl3/main.cpp +++ b/examples/example_glfw_opengl3/main.cpp @@ -189,11 +189,14 @@ int main(int, char**) ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); // Update and Render additional Platform Windows + // (Platform functions may change the current OpenGL context, so we save/restore it to make it easier to paste this code elsewhere. + // For this specific demo app we could also call glfwMakeContextCurrent(window) directly) if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + GLFWwindow* backup_current_context = glfwGetCurrentContext(); ImGui::UpdatePlatformWindows(); ImGui::RenderPlatformWindowsDefault(); - glfwMakeContextCurrent(window); + glfwMakeContextCurrent(backup_current_context); } glfwSwapBuffers(window); diff --git a/examples/example_sdl_opengl2/main.cpp b/examples/example_sdl_opengl2/main.cpp index d27606b7..47a5f4d2 100644 --- a/examples/example_sdl_opengl2/main.cpp +++ b/examples/example_sdl_opengl2/main.cpp @@ -147,11 +147,15 @@ int main(int, char**) ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData()); // Update and Render additional Platform Windows + // (Platform functions may change the current OpenGL context, so we save/restore it to make it easier to paste this code elsewhere. + // For this specific demo app we could also call SDL_GL_MakeCurrent(window, gl_context) directly) if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + SDL_Window* backup_current_window = SDL_GL_GetCurrentWindow(); + SDL_GLContext backup_current_context = SDL_GL_GetCurrentContext(); ImGui::UpdatePlatformWindows(); ImGui::RenderPlatformWindowsDefault(); - SDL_GL_MakeCurrent(window, gl_context); + SDL_GL_MakeCurrent(backup_current_window, backup_current_context); } SDL_GL_SwapWindow(window); diff --git a/examples/example_sdl_opengl3/main.cpp b/examples/example_sdl_opengl3/main.cpp index f3aae2ff..fc777e30 100644 --- a/examples/example_sdl_opengl3/main.cpp +++ b/examples/example_sdl_opengl3/main.cpp @@ -188,11 +188,15 @@ int main(int, char**) ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); // Update and Render additional Platform Windows + // (Platform functions may change the current OpenGL context, so we save/restore it to make it easier to paste this code elsewhere. + // For this specific demo app we could also call SDL_GL_MakeCurrent(window, gl_context) directly) if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + SDL_Window* backup_current_window = SDL_GL_GetCurrentWindow(); + SDL_GLContext backup_current_context = SDL_GL_GetCurrentContext(); ImGui::UpdatePlatformWindows(); ImGui::RenderPlatformWindowsDefault(); - SDL_GL_MakeCurrent(window, gl_context); + SDL_GL_MakeCurrent(backup_current_window, backup_current_context); } SDL_GL_SwapWindow(window); diff --git a/imgui.cpp b/imgui.cpp index a9b1fd70..3b78289a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3812,10 +3812,12 @@ void ImGui::EndFrame() viewport->LastPos = viewport->Pos; if (viewport->LastFrameActive < g.FrameCount || viewport->Size.x <= 0.0f || viewport->Size.y <= 0.0f) continue; - if (viewport->Window && !IsWindowActiveAndVisible(viewport->Window)) + if (viewport->Window && !IsWindowActiveAndVisible(viewport->Window)) // Will be destroyed in UpdatePlatformWindows() continue; if (i > 0) IM_ASSERT(viewport->Window != NULL); + + // Add to user-facing list g.PlatformIO.Viewports.push_back(viewport); } g.Viewports[0]->ClearRequestFlags(); // Clear main viewport flags because UpdatePlatformWindows() won't do it and may not even be called @@ -7680,11 +7682,9 @@ void ImGui::UpdatePlatformWindows() DestroyPlatformWindow(viewport); continue; } - if (viewport->LastFrameActive < g.FrameCount) - continue; // New windows that appears directly in a new viewport won't always have a size on their first frame - if (viewport->Size.x <= 0 || viewport->Size.y <= 0) + if (viewport->LastFrameActive < g.FrameCount || viewport->Size.x <= 0 || viewport->Size.y <= 0) continue; // Update common viewport flags for owned viewports diff --git a/imgui_internal.h b/imgui_internal.h index 56f4f352..151b7a4b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -651,6 +651,7 @@ enum ImGuiViewportFlagsPrivate_ }; // ImGuiViewport Private/Internals fields (cardinal sin: we are using inheritance!) +// Note that every instance of ImGuiViewport is in fact a ImGuiViewportP. struct ImGuiViewportP : public ImGuiViewport { int Idx; From a9a60a24c159e15935453078be9e59d19118ca32 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 23 Dec 2018 17:39:04 +0100 Subject: [PATCH 03/14] Tweaked asserts --- examples/imgui_impl_glfw.cpp | 4 ++-- examples/imgui_impl_sdl.cpp | 2 +- examples/imgui_impl_win32.cpp | 1 + imgui.cpp | 17 +++++++++++++---- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index 2122c601..6c6f452d 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -267,9 +267,9 @@ static void ImGui_ImplGlfw_UpdateMouseCursor() void ImGui_ImplGlfw_NewFrame() { ImGuiIO& io = ImGui::GetIO(); - IM_ASSERT(io.Fonts->IsBuilt()); // Font atlas needs to be built, call renderer _NewFrame() function e.g. ImGui_ImplOpenGL3_NewFrame() + IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame()."); - // Setup display size + // Setup display size (every frame to accommodate for window resizing) int w, h; int display_w, display_h; glfwGetWindowSize(g_Window, &w, &h); diff --git a/examples/imgui_impl_sdl.cpp b/examples/imgui_impl_sdl.cpp index 730bce80..fbd420a6 100644 --- a/examples/imgui_impl_sdl.cpp +++ b/examples/imgui_impl_sdl.cpp @@ -271,7 +271,7 @@ static void ImGui_ImplSDL2_UpdateMouseCursor() void ImGui_ImplSDL2_NewFrame(SDL_Window* window) { ImGuiIO& io = ImGui::GetIO(); - IM_ASSERT(io.Fonts->IsBuilt()); // Font atlas needs to be built, call renderer _NewFrame() function e.g. ImGui_ImplOpenGL3_NewFrame() + IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame()."); // Setup display size (every frame to accommodate for window resizing) int w, h; diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index 9bf8a81d..402025b3 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -142,6 +142,7 @@ static void ImGui_ImplWin32_UpdateMousePos() void ImGui_ImplWin32_NewFrame() { ImGuiIO& io = ImGui::GetIO(); + IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame()."); // Setup display size (every frame to accommodate for window resizing) RECT rect; diff --git a/imgui.cpp b/imgui.cpp index 38a393e4..1629ebac 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3553,7 +3553,7 @@ void ImGui::EndFrame() IM_ASSERT(g.Initialized); if (g.FrameCountEnded == g.FrameCount) // Don't process EndFrame() multiple times. return; - IM_ASSERT(g.FrameScopeActive && "Forgot to call ImGui::NewFrame()"); + IM_ASSERT(g.FrameScopeActive && "Forgot to call ImGui::NewFrame()?"); // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME) if (g.IO.ImeSetInputScreenPosFn && ImLengthSqr(g.PlatformImeLastPos - g.PlatformImePos) > 0.0001f) @@ -3562,8 +3562,17 @@ void ImGui::EndFrame() g.PlatformImeLastPos = g.PlatformImePos; } - // Hide implicit "Debug" window if it hasn't been used - IM_ASSERT(g.CurrentWindowStack.Size == 1); // Mismatched Begin()/End() calls, did you forget to call end on g.CurrentWindow->Name? + // Report when there is a mismatch of Begin/BeginChild vs End/EndChild calls. Important: Remember that the Begin/BeginChild API requires you + // to always call End/EndChild even if Begin/BeginChild returns false! (this is unfortunately inconsistent with most other Begin* API). + if (g.CurrentWindowStack.Size != 1) + { + if (g.CurrentWindowStack.Size > 1) + IM_ASSERT(g.CurrentWindowStack.Size == 1 && "Mismatched Begin/BeginChild vs End/EndChild calls: did you forget to call End/EndChild?"); + else + IM_ASSERT(g.CurrentWindowStack.Size == 1 && "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?"); + } + + // Hide implicit/fallback "Debug" window if it hasn't been used if (g.CurrentWindow && !g.CurrentWindow->WriteAccessed) g.CurrentWindow->Active = false; End(); @@ -3699,7 +3708,7 @@ void ImGui::Render() g.IO.MetricsRenderVertices = g.DrawData.TotalVtxCount; g.IO.MetricsRenderIndices = g.DrawData.TotalIdxCount; - // Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData() + // (Legacy) Call the Render callback function. The current prefer way is to let the user retrieve GetDrawData() and call the render function themselves. #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS if (g.DrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL) g.IO.RenderDrawListsFn(&g.DrawData); From d8451352737c08a5ee22b0d805415cb4a8327e5b Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 23 Dec 2018 17:54:20 +0100 Subject: [PATCH 04/14] Error recovery: Extraneous/undesired calls to End() are now being caught by an assert in the End() function itself at the call site (instead of being reported in EndFrame). Past the assert, they don't lead to crashes any more. Missing calls to End(), pass the assert, should not lead to crashes any more, nor to the fallback/debug window appearing on screen. (#1651). --- docs/CHANGELOG.txt | 4 ++++ imgui.cpp | 19 ++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e2ac095f..5d7bad6a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -62,6 +62,10 @@ Other Changes: This affects clamping window within the visible area: with this option enabled title bars need to be visible. (#899) - Window: Fixed using SetNextWindowPos() on a child window (which wasn't really documented) position the cursor as expected in the parent window, so there is no mismatch between the layout in parent and the position of the child window. +- Error recovery: Extraneous/undesired calls to End() are now being caught by an assert in the End() function itself + at the call site (instead of being reported in EndFrame). Past the assert, they don't lead to crashes any more. (#1651) +- Error recovery: Missing calls to End(), pass the assert, should not lead to crashes or to the fallback Debug window + appearing on screen, (#1651). - IO: Added BackendPlatformUserData, BackendRendererUserData, BackendLanguageUserData void* for storage use by back-ends. - Style: Tweaked default value of style.DisplayWindowPadding from (20,20) to (19,19) so the default style as a value which is the same as the title bar height. diff --git a/imgui.cpp b/imgui.cpp index 1629ebac..f33d7d5e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3555,6 +3555,9 @@ void ImGui::EndFrame() return; IM_ASSERT(g.FrameScopeActive && "Forgot to call ImGui::NewFrame()?"); + g.FrameScopeActive = false; + g.FrameCountEnded = g.FrameCount; + // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME) if (g.IO.ImeSetInputScreenPosFn && ImLengthSqr(g.PlatformImeLastPos - g.PlatformImePos) > 0.0001f) { @@ -3567,9 +3570,15 @@ void ImGui::EndFrame() if (g.CurrentWindowStack.Size != 1) { if (g.CurrentWindowStack.Size > 1) + { IM_ASSERT(g.CurrentWindowStack.Size == 1 && "Mismatched Begin/BeginChild vs End/EndChild calls: did you forget to call End/EndChild?"); + while (g.CurrentWindowStack.Size > 1) // FIXME-ERRORHANDLING + End(); + } else + { IM_ASSERT(g.CurrentWindowStack.Size == 1 && "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?"); + } } // Hide implicit/fallback "Debug" window if it hasn't been used @@ -3665,9 +3674,6 @@ void ImGui::EndFrame() g.IO.MouseWheel = g.IO.MouseWheelH = 0.0f; memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters)); memset(g.IO.NavInputs, 0, sizeof(g.IO.NavInputs)); - - g.FrameScopeActive = false; - g.FrameCountEnded = g.FrameCount; } void ImGui::Render() @@ -5251,6 +5257,13 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_first_use, void ImGui::End() { ImGuiContext& g = *GImGui; + + if (g.CurrentWindowStack.Size <= 1 && g.FrameScopeActive) + { + IM_ASSERT(g.CurrentWindowStack.Size > 1 && "Calling End() too many times!"); + return; // FIXME-ERRORHANDLING + } + ImGuiWindow* window = g.CurrentWindow; if (window->DC.ColumnsSet != NULL) From e21bc446847474681c70e564eda28a85f6e1ae51 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 2 Jan 2019 09:57:25 +0100 Subject: [PATCH 05/14] Comments: fixed missing line in the "how a simple rendering function may look like" section (#2258) --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index f33d7d5e..ebb54903 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -259,6 +259,7 @@ CODE // TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragment shader sample color from 1 texture, multiply by vertex color. for (int n = 0; n < draw_data->CmdListsCount; n++) { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; // vertex buffer generated by ImGui const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; // index buffer generated by ImGui for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) From 6b97ded438c6d4d81835cd01f81e2e372f0bbe90 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 2 Jan 2019 10:57:57 +0100 Subject: [PATCH 06/14] Happy new year! & comments --- LICENSE.txt | 2 +- docs/README.md | 2 +- imgui.cpp | 128 +++++++++++++++++++++++++++++-------------------- imgui.h | 8 ++-- 4 files changed, 82 insertions(+), 58 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 21b6ee7e..3b439aa4 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014-2018 Omar Cornut +Copyright (c) 2014-2019 Omar Cornut Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/docs/README.md b/docs/README.md index e396a108..809f19f8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -236,7 +236,7 @@ The library started its life and is best known as "ImGui" only due to the fact t **How can I tell whether to dispatch mouse/keyboard to imgui or to my application?**
**How can I display an image? What is ImTextureID, how does it works?** -
**How can I have multiple widgets with the same label or without a label? A primer on labels and the ID Stack.** +
**How can I have multiple widgets with the same label or with an empty label? A primer on labels and the ID Stack.**
**How can I use my own math types instead of ImVec2/ImVec4?**
**How can I load a different font than the default?**
**How can I easily use icons in my application?** diff --git a/imgui.cpp b/imgui.cpp index ebb54903..82fcb9af 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7,9 +7,12 @@ // Releases change-log at https://github.com/ocornut/imgui/releases // Technical Support for Getting Started https://discourse.dearimgui.org/c/getting-started // Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/1269 + // Developed by Omar Cornut and every direct or indirect contributors to the GitHub. +// See LICENSE.txt for copyright and licensing details (standard MIT License). // This library is free but I need your support to sustain development and maintenance. -// If you work for a company, please consider financial support, see README. For individuals: https://www.patreon.com/imgui +// Businesses: you can support continued maintenance and development via support contracts or sponsoring, see docs/README. +// Individuals: you can support continued maintenance and development via donations or Patreon https://www.patreon.com/imgui. // It is recommended that you don't modify imgui.cpp! It will become difficult for you to update the library. // Note that 'ImGui::' being a namespace, you can add functions into the namespace from your own source files, without @@ -26,17 +29,17 @@ DOCUMENTATION - MISSION STATEMENT - END-USER GUIDE - PROGRAMMER GUIDE (read me!) - - Read first - - How to update to a newer version of Dear ImGui - - Getting started with integrating Dear ImGui in your code/engine - - This is how a simple application may look like (2 variations) - - This is how a simple rendering function may look like - - Using gamepad/keyboard navigation controls + - Read first. + - How to update to a newer version of Dear ImGui. + - Getting started with integrating Dear ImGui in your code/engine. + - This is how a simple application may look like (2 variations). + - This is how a simple rendering function may look like. + - Using gamepad/keyboard navigation controls. - API BREAKING CHANGES (read me when you update!) - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS - How can I tell whether to dispatch mouse/keyboard to imgui or to my application? - How can I display an image? What is ImTextureID, how does it works? - - How can I have multiple widgets with the same label or without a label? A primer on labels and the ID Stack. + - How can I have multiple widgets with the same label or with an empty label? A primer on labels and the ID Stack. - How can I use my own math types instead of ImVec2/ImVec4? - How can I load a different font than the default? - How can I easily use icons in my application? @@ -84,19 +87,19 @@ CODE MISSION STATEMENT ================= - - Easy to use to create code-driven and data-driven tools - - Easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools - - Easy to hack and improve - - Minimize screen real-estate usage - - Minimize setup and maintenance - - Minimize state storage on user side - - Portable, minimize dependencies, run on target (consoles, phones, etc.) - - Efficient runtime and memory consumption (NB- we do allocate when "growing" content e.g. creating a window, - opening a tree node for the first time, etc. but a typical frame should not allocate anything) + - Easy to use to create code-driven and data-driven tools. + - Easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools. + - Easy to hack and improve. + - Minimize screen real-estate usage. + - Minimize setup and maintenance. + - Minimize state storage on user side. + - Portable, minimize dependencies, run on target (consoles, phones, etc.). + - Efficient runtime and memory consumption (NB- we do allocate when "growing" content e.g. creating a window,. + opening a tree node for the first time, etc. but a typical frame should not allocate anything). Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes: - - Doesn't look fancy, doesn't animate - - Limited layout features, intricate layouts are typically crafted in code + - Doesn't look fancy, doesn't animate. + - Limited layout features, intricate layouts are typically crafted in code. END-USER GUIDE @@ -126,16 +129,29 @@ CODE PROGRAMMER GUIDE ================ - READ FIRST + READ FIRST: - Read the FAQ below this section! - Your code creates the UI, if your code doesn't run the UI is gone! The UI can be highly dynamic, there are no construction or destruction steps, less superfluous data retention on your side, less state duplication, less state synchronization, less bugs. - Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features. - - You can learn about immediate-mode GUI principles at http://www.johno.se/book/imgui.html or watch http://mollyrocket.com/861 - See README.md for more links describing the IMGUI paradigm. Dear ImGui is an implementation of the IMGUI paradigm. + - The library is designed to be built from sources. Avoid pre-compiled binaries and packaged versions. See imconfig.h to configure your build. + - Dear ImGui is an implementation of the IMGUI paradigm (immediate-mode graphical user interface, a term coined by Casey Muratori). + You can learn about IMGUI principles at http://www.johno.se/book/imgui.html, http://mollyrocket.com/861 & more links docs/README.md. + - Dear ImGui is a "single pass" rasterizing implementation of the IMGUI paradigm, aimed at ease of use and high-performances. + For every application frame your UI code will be called only once. This is in contrast to e.g. Unity's own implementation of an IMGUI, + where the UI code is called multiple times ("multiple passes") from a single entry point. There are pros and cons to both approaches. + - Our origin are on the top-left. In axis aligned bounding boxes, Min = top-left, Max = bottom-right. + - This codebase is also optimized to yield decent performances with typical "Debug" builds settings. + - Please make sure you have asserts enabled (IM_ASSERT redirects to assert() by default, but can be redirected). + If you get an assert, read the messages and comments around the assert. + - C++: this is a very C-ish codebase: we don't rely on C++11, we don't include any C++ headers, and ImGui:: is a namespace. + - C++: ImVec2/ImVec4 do not expose math operators by default, because it is expected that you use your own math types. + See FAQ "How can I use my own math types instead of ImVec2/ImVec4?" for details about setting up imconfig.h for that. + However, imgui_internal.h can optionally export math operators for ImVec2/ImVec4, which we use in this codebase. + - C++: pay attention that ImVector<> manipulates plain-old-data and does not honor construction/destruction (avoid using it in your code!). - HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI + HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI: - Overwrite all the sources files except for imconfig.h (if you have made modification to your copy of imconfig.h) - Or maintain your own branch where you have imconfig.h modified. @@ -145,7 +161,7 @@ CODE likely be a comment about it. Please report any issue to the GitHub page! - Try to keep your copy of dear imgui reasonably up to date. - GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE + GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE: - Run and study the examples and demo in imgui_demo.cpp to get acquainted with the library. - Add the Dear ImGui source files to your projects or using your preferred build system. @@ -158,8 +174,8 @@ CODE - Refer to the bindings and demo applications in the examples/ folder for instruction on how to setup your code. - If you are running over a standard OS with a common graphics API, you should be able to use unmodified imgui_impl_*** files from the examples/ folder. - HOW A SIMPLE APPLICATION MAY LOOK LIKE - EXHIBIT 1: USING THE EXAMPLE BINDINGS (imgui_impl_XXX.cpp files from the examples/ folder) + HOW A SIMPLE APPLICATION MAY LOOK LIKE: + EXHIBIT 1: USING THE EXAMPLE BINDINGS (imgui_impl_XXX.cpp files from the examples/ folder). // Application init: create a dear imgui context, setup some options, load fonts ImGui::CreateContext(); @@ -194,8 +210,8 @@ CODE ImGui_ImplWin32_Shutdown(); ImGui::DestroyContext(); - HOW A SIMPLE APPLICATION MAY LOOK LIKE - EXHIBIT 2: IMPLEMENTING CUSTOM BINDING / CUSTOM ENGINE + HOW A SIMPLE APPLICATION MAY LOOK LIKE: + EXHIBIT 2: IMPLEMENTING CUSTOM BINDING / CUSTOM ENGINE. // Application init: create a dear imgui context, setup some options, load fonts ImGui::CreateContext(); @@ -249,12 +265,12 @@ CODE // Shutdown ImGui::DestroyContext(); - HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE + HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE: void void MyImGuiRenderFunction(ImDrawData* draw_data) { // TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - // TODO: Setup viewport using draw_data->DisplaySize + // TODO: Setup viewport covering draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize // TODO: Setup orthographic projection matrix cover draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize // TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragment shader sample color from 1 texture, multiply by vertex color. for (int n = 0; n < draw_data->CmdListsCount; n++) @@ -468,7 +484,7 @@ CODE - the signature of the io.RenderDrawListsFn handler has changed! old: ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count) new: ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data). - argument: 'cmd_lists' becomes 'draw_data->CmdLists', 'cmd_lists_count' becomes 'draw_data->CmdListsCount' + parameters: 'cmd_lists' becomes 'draw_data->CmdLists', 'cmd_lists_count' becomes 'draw_data->CmdListsCount' ImDrawList: 'commands' becomes 'CmdBuffer', 'vtx_buffer' becomes 'VtxBuffer', 'IdxBuffer' is new. ImDrawCmd: 'vtx_count' becomes 'ElemCount', 'clip_rect' becomes 'ClipRect', 'user_callback' becomes 'UserCallback', 'texture_id' becomes 'TextureId'. - each ImDrawList now contains both a vertex buffer and an index buffer. For each command, render ElemCount/3 triangles using indices from the index buffer. @@ -501,9 +517,9 @@ CODE - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions. - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader. (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels. - font init: const void* png_data; unsigned int png_size; ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); <..Upload texture to GPU..> - became: unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); <..Upload texture to GPU>; io.Fonts->TexId = YourTextureIdentifier; - you now more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs. + font init: { const void* png_data; unsigned int png_size; ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); <..Upload texture to GPU..>; } + became: { unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); <..Upload texture to GPU>; io.Fonts->TexId = YourTextureIdentifier; } + you now have more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs. it is now recommended that you sample the font texture with bilinear interpolation. (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID. (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix) @@ -625,7 +641,7 @@ CODE Finally, you may call ImGui::ShowMetricsWindow() to explore/visualize/understand how the ImDrawList are generated. - Q: How can I have multiple widgets with the same label or without a label? + Q: How can I have multiple widgets with the same label or with an empty label? Q: I have multiple widgets with the same label, and only the first one works. Why is that? A: A primer on labels and the ID Stack... @@ -647,6 +663,9 @@ CODE Begin("MyWindow"); Button("OK"); // Label = "OK", ID = hash of ("MyWindow", "OK") End(); + Begin("MyOtherWindow"); + Button("OK"); // Label = "OK", ID = hash of ("MyOtherWindow", "OK") + End(); - If you have a same ID twice in the same location, you'll have a conflict: @@ -686,47 +705,48 @@ CODE within the same window. This is the most convenient way of distinguishing ID when iterating and creating many UI elements programmatically. You can push a pointer, a string or an integer value into the ID stack. - Remember that ID are formed from the concatenation of _everything_ in the ID stack! + Remember that ID are formed from the concatenation of _everything_ pushed into the ID stack. + At each level of the stack we store the seed used for items at this level of the ID stack. - Begin("Window"); + Begin("Window"); for (int i = 0; i < 100; i++) { - PushID(i); // Push i to the id tack - Button("Click"); // Label = "Click", ID = Hash of ("Window", i, "Click") + PushID(i); // Push i to the id tack + Button("Click"); // Label = "Click", ID = hash of ("Window", i, "Click") PopID(); } for (int i = 0; i < 100; i++) { MyObject* obj = Objects[i]; PushID(obj); - Button("Click"); // Label = "Click", ID = Hash of ("Window", obj pointer, "Click") + Button("Click"); // Label = "Click", ID = hash of ("Window", obj pointer, "Click") PopID(); } for (int i = 0; i < 100; i++) { MyObject* obj = Objects[i]; PushID(obj->Name); - Button("Click"); // Label = "Click", ID = Hash of ("Window", obj->Name, "Click") + Button("Click"); // Label = "Click", ID = hash of ("Window", obj->Name, "Click") PopID(); } End(); - - More example showing that you can stack multiple prefixes into the ID stack: + - You can stack multiple prefixes into the ID stack: - Button("Click"); // Label = "Click", ID = hash of (..., "Click") + Button("Click"); // Label = "Click", ID = hash of (..., "Click") PushID("node"); - Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click") + Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click") PushID(my_ptr); - Button("Click"); // Label = "Click", ID = hash of (..., "node", my_ptr, "Click") + Button("Click"); // Label = "Click", ID = hash of (..., "node", my_ptr, "Click") PopID(); PopID(); - Tree nodes implicitly creates a scope for you by calling PushID(). - Button("Click"); // Label = "Click", ID = hash of (..., "Click") - if (TreeNode("node")) + Button("Click"); // Label = "Click", ID = hash of (..., "Click") + if (TreeNode("node")) // <-- this function call will do a PushID() for you (unless instructed not to, with a special flag) { - Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click") + Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click") TreePop(); } @@ -746,7 +766,8 @@ CODE ImGuiIO& io = ImGui::GetIO(); io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels); io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() - Default is ProggyClean.ttf, rendered at size 13, embedded in dear imgui's source code. + Default is ProggyClean.ttf, monospace, rendered at size 13, embedded in dear imgui's source code. + (Tip: monospace fonts are convenient because they allow to facilitate horizontal alignment directly at the string level.) (Read the 'misc/fonts/README.txt' file for more details about font loading.) New programmers: remember that in C/C++ and most programming languages if you want to use a @@ -758,6 +779,7 @@ CODE Q: How can I easily use icons in my application? A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you main font. Then you can refer to icons within your strings. + You may want to see ImFontConfig::GlyphMinAdvanceX to make your icon look monospace to facilitate alignment. (Read the 'misc/fonts/README.txt' file for more details about icons font loading.) Q: How can I load multiple fonts? @@ -847,10 +869,12 @@ CODE Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height). Q: How can I help? - A: - If you are experienced with Dear ImGui and C++, look at the github issues, or docs/TODO.txt and see how you want/can help! - - Convince your company to sponsor/fund development! Individual users: you can also become a Patron (patreon.com/imgui) or donate on PayPal! See README. + A: - If you are experienced with Dear ImGui and C++, look at the github issues, look at the Wiki, read docs/TODO.txt + and see how you want to help and can help! + - Businesses: convince your company to fund development via support contracts/sponsoring! This is among the most useful thing you can do for dear imgui. + - Individuals: you can also become a Patron (http://www.patreon.com/imgui) or donate on PayPal! See README. - Disclose your usage of dear imgui via a dev blog post, a tweet, a screenshot, a mention somewhere etc. - You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/1269). Visuals are ideal as they inspire other programmers. + You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/1902). Visuals are ideal as they inspire other programmers. But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions. - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues (on github or privately). diff --git a/imgui.h b/imgui.h index 98e34e19..081cd5d0 100644 --- a/imgui.h +++ b/imgui.h @@ -3,7 +3,7 @@ // See imgui.cpp file for documentation. // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. -// Read 'Programmer guide' in imgui.cpp for notes on how to setup ImGui in your codebase. +// Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase. // Get latest version at https://github.com/ocornut/imgui /* @@ -94,11 +94,11 @@ struct ImDrawVert; // A single vertex (20 bytes by default, ove struct ImFont; // Runtime data for a single font within a parent ImFontAtlas struct ImFontAtlas; // Runtime data for multiple fonts, bake multiple fonts into a single texture, TTF/OTF font loader struct ImFontConfig; // Configuration data when adding a font or merging fonts -struct ImColor; // Helper functions to create a color that can be converted to either u32 or float4 (*obsolete* please avoid using) +struct ImColor; // Helper functions to create a color that can be converted to either u32 or float4 (*OBSOLETE* please avoid using) #ifndef ImTextureID typedef void* ImTextureID; // User data to identify a texture (this is whatever to you want it to be! read the FAQ about ImTextureID in imgui.cpp) #endif -struct ImGuiContext; // ImGui context (opaque) +struct ImGuiContext; // Dear ImGui context (opaque structure, unless including imgui_internal.h) struct ImGuiIO; // Main configuration and I/O between your application and ImGui struct ImGuiInputTextCallbackData; // Shared state of InputText() when using custom ImGuiInputTextCallback (rare/advanced use) struct ImGuiListClipper; // Helper to manually clip large list of items @@ -113,7 +113,7 @@ struct ImGuiTextBuffer; // Helper to hold and append into a text buf // Typedefs and Enums/Flags (declared as int for compatibility with old C++, to allow using as flags and to not pollute the top of this file) // Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists. typedef unsigned int ImGuiID; // Unique ID used by widgets (typically hashed from a stack of string) -typedef unsigned short ImWchar; // Character for keyboard input/display +typedef unsigned short ImWchar; // A single U16 character for keyboard input/display. We encode them as multi bytes UTF-8 when used in strings. typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling typedef int ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for Set*() typedef int ImGuiDataType; // -> enum ImGuiDataType_ // Enum: A primary data type From c738f9ef92af3f84702e781686954422abaebfa9 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 2 Jan 2019 11:03:56 +0100 Subject: [PATCH 07/14] InputFloat: When using ImGuiInputTextFlags_ReadOnly the step buttons are disabled. (#2257) --- docs/CHANGELOG.txt | 1 + imgui_demo.cpp | 2 +- imgui_widgets.cpp | 7 +++++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5d7bad6a..df5b685b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -62,6 +62,7 @@ Other Changes: This affects clamping window within the visible area: with this option enabled title bars need to be visible. (#899) - Window: Fixed using SetNextWindowPos() on a child window (which wasn't really documented) position the cursor as expected in the parent window, so there is no mismatch between the layout in parent and the position of the child window. +- InputFloat: When using ImGuiInputTextFlags_ReadOnly the step buttons are disabled. (#2257) - Error recovery: Extraneous/undesired calls to End() are now being caught by an assert in the End() function itself at the call site (instead of being reported in EndFrame). Past the assert, they don't lead to crashes any more. (#1651) - Error recovery: Missing calls to End(), pass the assert, should not lead to crashes or to the fallback Debug window diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 9e7b748b..a5f8f86c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -480,7 +480,7 @@ static void ShowDemoWindowWidgets() ImGui::SameLine(); ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n"); static float f0 = 0.001f; - ImGui::InputFloat("input float", &f0, 0.01f, 1.0f); + ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f"); static double d0 = 999999.00000001; ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.8f"); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 367b9bb6..1b764e30 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2666,14 +2666,17 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p PopItemWidth(); // Step buttons + ImGuiButtonFlags button_flags = ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups; + if (extra_flags & ImGuiInputTextFlags_ReadOnly) + button_flags |= ImGuiButtonFlags_Disabled; SameLine(0, style.ItemInnerSpacing.x); - if (ButtonEx("-", ImVec2(button_size, button_size), ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) + if (ButtonEx("-", ImVec2(button_size, button_size), button_flags)) { DataTypeApplyOp(data_type, '-', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast ? step_fast : step); value_changed = true; } SameLine(0, style.ItemInnerSpacing.x); - if (ButtonEx("+", ImVec2(button_size, button_size), ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) + if (ButtonEx("+", ImVec2(button_size, button_size), button_flags)) { DataTypeApplyOp(data_type, '+', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast ? step_fast : step); value_changed = true; From acacd93836485c47de71a2e6a6cd3488c0ccbe45 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 2 Jan 2019 11:08:14 +0100 Subject: [PATCH 08/14] Renamed extra_flags to flags in InputXXX parameters. --- imgui.h | 31 +++++++++---------- imgui_widgets.cpp | 76 +++++++++++++++++++++++------------------------ 2 files changed, 54 insertions(+), 53 deletions(-) diff --git a/imgui.h b/imgui.h index 081cd5d0..08cd8504 100644 --- a/imgui.h +++ b/imgui.h @@ -433,19 +433,20 @@ namespace ImGui // Widgets: Input with Keyboard // - If you want to use InputText() with a dynamic string type such as std::string or your own, see misc/cpp/imgui_stdlib.h + // - Most of the ImGuiInputTextFlags flags are only useful for InputText() and not for InputFloatX, InputIntX, InputDouble etc. IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0,0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, const char* format = "%.3f", ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputFloat2(const char* label, float v[2], const char* format = "%.3f", ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputFloat3(const char* label, float v[3], const char* format = "%.3f", ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputFloat4(const char* label, float v[4], const char* format = "%.3f", ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputInt2(const char* label, int v[2], ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputDouble(const char* label, double* v, double step = 0.0f, double step_fast = 0.0f, const char* format = "%.6f", ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputScalar(const char* label, ImGuiDataType data_type, void* v, const void* step = NULL, const void* step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* step = NULL, const void* step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, const char* format = "%.3f", ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputFloat2(const char* label, float v[2], const char* format = "%.3f", ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputFloat3(const char* label, float v[3], const char* format = "%.3f", ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputFloat4(const char* label, float v[4], const char* format = "%.3f", ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputDouble(const char* label, double* v, double step = 0.0f, double step_fast = 0.0f, const char* format = "%.6f", ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputScalar(const char* label, ImGuiDataType data_type, void* v, const void* step = NULL, const void* step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* step = NULL, const void* step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); // Widgets: Color Editor/Picker (tip: the ColorEdit* functions have a little colored preview square that can be left-clicked to open a picker, and right-clicked to open an option menu.) // - Note that in C++ a 'float v[X]' function argument is the _same_ as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. You can the pass the address of a first float element out of a contiguous structure, e.g. &myvector.x @@ -1413,10 +1414,10 @@ namespace ImGui // OBSOLETED in 1.63 (from Aug 2018) static inline bool IsItemDeactivatedAfterChange() { return IsItemDeactivatedAfterEdit(); } // OBSOLETED in 1.61 (from Apr 2018) - IMGUI_API bool InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags extra_flags = 0); // Use the 'const char* format' version instead of 'decimal_precision'! - IMGUI_API bool InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags flags = 0); // Use the 'const char* format' version instead of 'decimal_precision'! + IMGUI_API bool InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags flags = 0); + IMGUI_API bool InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags flags = 0); // OBSOLETED in 1.60 (from Dec 2017) static inline bool IsAnyWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_AnyWindow); } static inline bool IsAnyWindowHovered() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 1b764e30..18567602 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2633,7 +2633,7 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const c return false; } -bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_ptr, const void* step, const void* step_fast, const char* format, ImGuiInputTextFlags extra_flags) +bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_ptr, const void* step, const void* step_fast, const char* format, ImGuiInputTextFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -2650,9 +2650,9 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, data_ptr, format); bool value_changed = false; - if ((extra_flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0) - extra_flags |= ImGuiInputTextFlags_CharsDecimal; - extra_flags |= ImGuiInputTextFlags_AutoSelectAll; + if ((flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0) + flags |= ImGuiInputTextFlags_CharsDecimal; + flags |= ImGuiInputTextFlags_AutoSelectAll; if (step != NULL) { @@ -2661,13 +2661,13 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p BeginGroup(); // The only purpose of the group here is to allow the caller to query item data e.g. IsItemActive() PushID(label); PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2)); - if (InputText("", buf, IM_ARRAYSIZE(buf), extra_flags)) // PushId(label) + "" gives us the expected ID from outside point of view + if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialText.Data, data_type, data_ptr, format); PopItemWidth(); // Step buttons ImGuiButtonFlags button_flags = ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups; - if (extra_flags & ImGuiInputTextFlags_ReadOnly) + if (flags & ImGuiInputTextFlags_ReadOnly) button_flags |= ImGuiButtonFlags_Disabled; SameLine(0, style.ItemInnerSpacing.x); if (ButtonEx("-", ImVec2(button_size, button_size), button_flags)) @@ -2689,14 +2689,14 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p } else { - if (InputText(label, buf, IM_ARRAYSIZE(buf), extra_flags)) + if (InputText(label, buf, IM_ARRAYSIZE(buf), flags)) value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialText.Data, data_type, data_ptr, format); } return value_changed; } -bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* step, const void* step_fast, const char* format, ImGuiInputTextFlags extra_flags) +bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* step, const void* step_fast, const char* format, ImGuiInputTextFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -2711,7 +2711,7 @@ bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* v, in for (int i = 0; i < components; i++) { PushID(i); - value_changed |= InputScalar("##v", data_type, v, step, step_fast, format, extra_flags); + value_changed |= InputScalar("##v", data_type, v, step, step_fast, format, flags); SameLine(0, g.Style.ItemInnerSpacing.x); PopID(); PopItemWidth(); @@ -2724,88 +2724,88 @@ bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* v, in return value_changed; } -bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, const char* format, ImGuiInputTextFlags extra_flags) +bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, const char* format, ImGuiInputTextFlags flags) { - extra_flags |= ImGuiInputTextFlags_CharsScientific; - return InputScalar(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), format, extra_flags); + flags |= ImGuiInputTextFlags_CharsScientific; + return InputScalar(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), format, flags); } -bool ImGui::InputFloat2(const char* label, float v[2], const char* format, ImGuiInputTextFlags extra_flags) +bool ImGui::InputFloat2(const char* label, float v[2], const char* format, ImGuiInputTextFlags flags) { - return InputScalarN(label, ImGuiDataType_Float, v, 2, NULL, NULL, format, extra_flags); + return InputScalarN(label, ImGuiDataType_Float, v, 2, NULL, NULL, format, flags); } -bool ImGui::InputFloat3(const char* label, float v[3], const char* format, ImGuiInputTextFlags extra_flags) +bool ImGui::InputFloat3(const char* label, float v[3], const char* format, ImGuiInputTextFlags flags) { - return InputScalarN(label, ImGuiDataType_Float, v, 3, NULL, NULL, format, extra_flags); + return InputScalarN(label, ImGuiDataType_Float, v, 3, NULL, NULL, format, flags); } -bool ImGui::InputFloat4(const char* label, float v[4], const char* format, ImGuiInputTextFlags extra_flags) +bool ImGui::InputFloat4(const char* label, float v[4], const char* format, ImGuiInputTextFlags flags) { - return InputScalarN(label, ImGuiDataType_Float, v, 4, NULL, NULL, format, extra_flags); + return InputScalarN(label, ImGuiDataType_Float, v, 4, NULL, NULL, format, flags); } // Prefer using "const char* format" directly, which is more flexible and consistent with other API. #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS -bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags extra_flags) +bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags flags) { char format[16] = "%f"; if (decimal_precision >= 0) ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision); - return InputFloat(label, v, step, step_fast, format, extra_flags); + return InputFloat(label, v, step, step_fast, format, flags); } -bool ImGui::InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags extra_flags) +bool ImGui::InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags flags) { char format[16] = "%f"; if (decimal_precision >= 0) ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision); - return InputScalarN(label, ImGuiDataType_Float, v, 2, NULL, NULL, format, extra_flags); + return InputScalarN(label, ImGuiDataType_Float, v, 2, NULL, NULL, format, flags); } -bool ImGui::InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags extra_flags) +bool ImGui::InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags flags) { char format[16] = "%f"; if (decimal_precision >= 0) ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision); - return InputScalarN(label, ImGuiDataType_Float, v, 3, NULL, NULL, format, extra_flags); + return InputScalarN(label, ImGuiDataType_Float, v, 3, NULL, NULL, format, flags); } -bool ImGui::InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags extra_flags) +bool ImGui::InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags flags) { char format[16] = "%f"; if (decimal_precision >= 0) ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision); - return InputScalarN(label, ImGuiDataType_Float, v, 4, NULL, NULL, format, extra_flags); + return InputScalarN(label, ImGuiDataType_Float, v, 4, NULL, NULL, format, flags); } #endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS -bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags extra_flags) +bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags flags) { // Hexadecimal input provided as a convenience but the flag name is awkward. Typically you'd use InputText() to parse your own data, if you want to handle prefixes. - const char* format = (extra_flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d"; - return InputScalar(label, ImGuiDataType_S32, (void*)v, (void*)(step>0 ? &step : NULL), (void*)(step_fast>0 ? &step_fast : NULL), format, extra_flags); + const char* format = (flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d"; + return InputScalar(label, ImGuiDataType_S32, (void*)v, (void*)(step>0 ? &step : NULL), (void*)(step_fast>0 ? &step_fast : NULL), format, flags); } -bool ImGui::InputInt2(const char* label, int v[2], ImGuiInputTextFlags extra_flags) +bool ImGui::InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags) { - return InputScalarN(label, ImGuiDataType_S32, v, 2, NULL, NULL, "%d", extra_flags); + return InputScalarN(label, ImGuiDataType_S32, v, 2, NULL, NULL, "%d", flags); } -bool ImGui::InputInt3(const char* label, int v[3], ImGuiInputTextFlags extra_flags) +bool ImGui::InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags) { - return InputScalarN(label, ImGuiDataType_S32, v, 3, NULL, NULL, "%d", extra_flags); + return InputScalarN(label, ImGuiDataType_S32, v, 3, NULL, NULL, "%d", flags); } -bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags extra_flags) +bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags) { - return InputScalarN(label, ImGuiDataType_S32, v, 4, NULL, NULL, "%d", extra_flags); + return InputScalarN(label, ImGuiDataType_S32, v, 4, NULL, NULL, "%d", flags); } -bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags extra_flags) +bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags flags) { - extra_flags |= ImGuiInputTextFlags_CharsScientific; - return InputScalar(label, ImGuiDataType_Double, (void*)v, (void*)(step>0.0 ? &step : NULL), (void*)(step_fast>0.0 ? &step_fast : NULL), format, extra_flags); + flags |= ImGuiInputTextFlags_CharsScientific; + return InputScalar(label, ImGuiDataType_Double, (void*)v, (void*)(step>0.0 ? &step : NULL), (void*)(step_fast>0.0 ? &step_fast : NULL), format, flags); } //------------------------------------------------------------------------- From c017a4fb5f92a77ba05f24b666a62b210119c37b Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 2 Jan 2019 14:28:49 +0100 Subject: [PATCH 09/14] Moved guidelines to issue #2261 to Pin and increase visibility for now. --- .github/CONTRIBUTING.md | 44 +------------------------------- .github/issue_template.md | 23 +++++++++-------- .github/pull_request_template.md | 17 +++++++----- 3 files changed, 24 insertions(+), 60 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 5bbd8e15..84a39d29 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,43 +1 @@ -## How to create an Issue - -Hello! - -You may use the Issue Tracker to submit bug reports, feature requests or suggestions. You may ask for help or advice as well. However please read this wall of text before doing so. The amount of incomplete or ambiguous requests due to people not following those guidelines is often overwhelming. Please do your best to clarify your request. Thank you! - -**IF YOU ARE HAVING AN ISSUE COMPILING/LINKING/RUNNING/DISPLAYING/ADDING FONTS/WIRING INPUTS** -- Please post on the "Getting Started" Discourse forum: https://discourse.dearimgui.org/c/getting-started - -**Prerequisites for new users of dear imgui:** -- Please read the FAQ in imgui.cpp. -- Please read misc/fonts/README.txt if your question relates to fonts or text. -- Please run ImGui::ShowDemoWindow() to explore the demo and its sources. -- Please use the Search function of GitHub to look for similar issues. You may also browse issues by tags. -- Please use the Search function of your IDE to search in the code for comments related to your situation. -- If you get a assert, use a debugger to locate the line triggering it and read the comments around the assert. - -**Guidelines to report an issue or ask a question:** -- Please provide your imgui version number. -- Please state if you have made substantial modifications to your copy of imgui. -- Try to be explicit with your Goals, your Expectations and what you have Tried. What you have in mind or in your code is not obvious to other people. People frequently discuss problems without first mentioning their goal. -- If you are discussing an assert or a crash, please provide a debugger callstack. Never state "it crashes" without additional information. If you don't know how to use a debugger and retrieve a callstack, learning about it will be useful. -- Please make sure that your compilation settings have asserts enabled. Calls to IM_ASSERT() are scattered in the code to help catch common issues. By default IM_ASSERT() calls the standard assert() function. To verify that your asserts are enabled, add the line `IM_ASSERT(false);` in your main() function. Your application should display an error message and abort. If your application report an error, it means that your asserts are disabled. Please make sure they are enabled. -- When discussing issues related to rendering or inputs, please state the OS/back-end/renderer you are using. Please state if you are using a vanilla copy of the example back-ends (imgui_impl_XXX files), or a modified one, or if you built your own. -- Please provide a Minimal, Complete and Verifiable Example ([MCVE](https://stackoverflow.com/help/mcve)) to demonstrate your problem. An ideal submission includes a small piece of code that anyone can paste in one of the examples/ application (e.g. in main.cpp or imgui_demo.cpp) to understand and reproduce it. Narrowing your problem to its shortest and purest form is the easiest way to understand it. Please test your shortened code to ensure it actually exhibit the problem. Often while creating the MCVE you will end up solving the problem! Many questions that are missing a standalone verifiable example are missing the actual cause of their issue in the description, which ends up wasting everyone's time. -- Try to attach screenshots to clarify the context. They often convey useful information that are omitted by the description. You can drag pictures/files here (prefer github attachments over 3rd party hosting). -- When requesting a new feature, please describe the usage context (how you intend to use it, why you need it, etc.). - -**Some unfortunate words of warning** -- If you are or were involved in cheating schemes (e.g. DLL injection) for competitive online multi-player games, please don't post here. We won't answer and you will be blocked. We've had too many of you. -- Due to frequent abuse of this service from aforementioned users, if your GitHub account is anonymous and was created five minutes ago please understand that your post will receive more scrutiny and incomplete questions may be dismissed. - -If you have been using dear imgui for a while or have been using C/C++ for several years or have demonstrated good behavior here, it is ok to not fullfill every item to the letter. Those are guidelines and experienced users or members of the community will know which information are useful in a given context. - -## How to create an Pull Request -- Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance forever. PR should be crafted both in the interest in the end-users and also to ease the maintainer into understanding and accepting it. -- When adding a feature, please describe the usage context (how you intend to use it, why you need it, etc.). -- When fixing a warning or compilation problem, please post the compiler log and specify the version and OS you are using. -- Try to attach screenshots to clarify the context and demonstrate the feature at a glance. You can drag pictures/files here (prefer github attachments over 3rd party hosting). -- Make sure your code follows the coding style already used in imgui (spaces instead of tabs, "local_variable", "FunctionName", "MemberName", etc.). We don't use modern C++ idioms and can compile without C++11. -- Make sure you create a branch for the pull request. In Git, 1 PR is associated to 1 branch. If you keep pushing to the same branch after you submitted the PR, your new commits will appear in the PR (we can still cherry-pick individual commits). - -Thank you for reading! +Please read https://github.com/ocornut/imgui/issues/2261 diff --git a/.github/issue_template.md b/.github/issue_template.md index 38a59532..2ce90bee 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1,11 +1,12 @@ (Click "Preview" to turn any http URL into a clickable link) -1. IF YOU ARE HAVING AN ISSUE COMPILING/LINKING/RUNNING/DISPLAYING/ADDING FONTS/WIRING INPUTS, please post on the "Getting Started" Discourse forum: +1. PLEASE CAREFULLY READ: +https://github.com/ocornut/imgui/issues/2261 + +2. IF YOU ARE HAVING AN ISSUE COMPILING/LINKING/RUNNING/DISPLAYING/ADDING FONTS, please post on the "Getting Started" Discourse forum: https://discourse.dearimgui.org/c/getting-started -2. You may use this Issue Tracker to ask for help and submit bug reports, feature requests or suggestions that don't fit in any category of (1). PLEASE CAREFULLY READ THE CONTRIBUTING DOCUMENT before submitting any issue: https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md - -3. PLEASE MAKE SURE that you have: read the FAQ in imgui.cpp; explored the contents of ShowDemoWindow() including the Examples menu; searched among Issues; used your IDE to search for keywords in all sources and text files; and read the CONTRIBUTING.md file linked above. +3. PLEASE MAKE SURE that you have: read the FAQ in imgui.cpp; explored the contents of ShowDemoWindow() including the Examples menu; searched among Issues; used your IDE to search for keywords in all sources and text files; and read the link provided in (1). 4. Delete points 1-4 and PLEASE FILL THE TEMPLATE BELOW before submitting your issue. @@ -21,19 +22,21 @@ Branch: XXX _(master/viewport/docking/etc.)_ **Back-end/Renderer/Compiler/OS** Back-ends: imgui_impl_XXX.cpp + imgui_impl_XXX.cpp _(or specify if using a custom engine/back-end)_ -Compiler: XXX _(if the question is related to building)_ +Compiler: XXX _(if the question is related to building or platform specific features)_ Operating System: XXX -**My Issue/Question:** _(please provide context)_ +**My Issue/Question:** -XXX +XXX _(please provide as much context as possible)_ -**Standalone, minimal, complete and verifiable example:** _(see CONTRIBUTING.md)_ +**Screenshots/Video** + +XXX _(you can drag files here)_ + +**Standalone, minimal, complete and verifiable example:** _(see https://github.com/ocornut/imgui/issues/2261)_ ``` // Please do not forget this! ImGui::Begin("Example Bug"); MoreCodeToExplainMyIssue(); ImGui::End(); ``` - -**Screenshots/Video** _(you can drag files here)_ diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 65ebcf24..ad66ea6f 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,9 +1,12 @@ -- Please read https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md -- Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance forever. PR should be crafted both in the interest in the end-users and also to ease the maintainer into understanding and accepting it. -- When adding a feature, please describe the usage context (how you intend to use it, why you need it, etc.). -- When adding a feature, try to attach screenshots/gifs to clarify the context and demonstrate the feature at a glance. -- When fixing a warning or compilation problem, post the compiler log and specify the version and OS you are using. -- Make sure your code follows the coding style already used in the codebase (4 spaces identation, no tabs, `type* name`, `local_variable`, `FunctionName()`, `MemberName`, `// Text Comment`, `//CodeComment()`, etc.). We don't use modern C++ idioms, we don't use C++ style cast, we don't use C++ headers, and we can compile without a C++11 compatible compiler. -- Make sure you create a branch for the pull request. In Git, 1 PR is associated to 1 branch. If you keep pushing to the same branch after you submitted the PR, your new commits will appear in the PR. +(Click "Preview" to turn any http URL into a clickable link) + +1. PLEASE CAREFULLY READ: +https://github.com/ocornut/imgui/issues/2261 + +2. PLEASE MAKE SURE YOU HAVE READ: +https://github.com/ocornut/imgui/issues/2261 + +3. DID I MENTION YOU SHOULD READ THIS? +https://github.com/ocornut/imgui/issues/2261 (Clear this form before submitting your PR) From d9a4cbc4296bc6579b88b66b21bd27f84f0d2d27 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 2 Jan 2019 16:04:13 +0100 Subject: [PATCH 10/14] Examples: Comments about GLFW/SDL versions --- examples/imgui_impl_glfw.cpp | 1 + examples/imgui_impl_sdl.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index 6c6f452d..0ff27446 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -1,6 +1,7 @@ // dear imgui: Platform Binding for GLFW // This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan..) // (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) +// (Requires: GLFW 3.1+) // Implemented features: // [X] Platform: Clipboard support. diff --git a/examples/imgui_impl_sdl.cpp b/examples/imgui_impl_sdl.cpp index fbd420a6..54ddc282 100644 --- a/examples/imgui_impl_sdl.cpp +++ b/examples/imgui_impl_sdl.cpp @@ -1,6 +1,7 @@ // dear imgui: Platform Binding for SDL2 // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) // (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.) +// (Requires: SDL 2.0. Prefer SDL 2.0.4+ for full feature support.) // Implemented features: // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. @@ -49,7 +50,6 @@ #define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE SDL_VERSION_ATLEAST(2,0,4) #define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6) -#define SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH SDL_VERSION_ATLEAST(2,0,5) #if !SDL_HAS_VULKAN static const Uint32 SDL_WINDOW_VULKAN = 0x10000000; #endif From 5305c322422e787f4b327a45284c9d08cec3cc44 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 21 Dec 2018 19:12:24 +0100 Subject: [PATCH 11/14] Viewport: Reorder flags. Set owned viewport common decoration flags in Begin(). Moved code in UpdateViewportsEndFrame() before we introduce family/class based overrides. --- imgui.cpp | 76 +++++++++++++++++++++++++----------------------- imgui.h | 14 ++++----- imgui_internal.h | 2 +- 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f9a8a65f..f18c61aa 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1010,7 +1010,8 @@ static void UpdateManualResize(ImGuiWindow* window, const ImVec2& si // Viewports const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using an arbitrary constant instead of e.g. ImHash("ViewportDefault", 0); so it's easier to spot in the debugger. The exact value doesn't matter. static ImGuiViewportP* AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const ImVec2& platform_pos, const ImVec2& size, ImGuiViewportFlags flags); -static void UpdateViewports(); +static void UpdateViewportsNewFrame(); +static void UpdateViewportsEndFrame(); static void UpdateSelectWindowViewport(ImGuiWindow* window); static bool UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImGuiViewportP* host_viewport); static void SetCurrentViewport(ImGuiWindow* window, ImGuiViewportP* viewport); @@ -3352,7 +3353,7 @@ void ImGui::NewFrame() g.WindowsActiveCount = 0; g.ConfigFlagsForFrame = g.IO.ConfigFlags; - UpdateViewports(); + UpdateViewportsNewFrame(); // Setup current font, and draw list shared data // FIXME-VIEWPORT: the concept of a single ClipRectFullscreen is not ideal! @@ -3846,24 +3847,8 @@ void ImGui::EndFrame() } } - // Update user-facing viewport list - g.PlatformIO.MainViewport = g.Viewports[0]; - g.PlatformIO.Viewports.resize(0); - for (int i = 0; i < g.Viewports.Size; i++) - { - ImGuiViewportP* viewport = g.Viewports[i]; - viewport->LastPos = viewport->Pos; - if (viewport->LastFrameActive < g.FrameCount || viewport->Size.x <= 0.0f || viewport->Size.y <= 0.0f) - continue; - if (viewport->Window && !IsWindowActiveAndVisible(viewport->Window)) // Will be destroyed in UpdatePlatformWindows() - continue; - if (i > 0) - IM_ASSERT(viewport->Window != NULL); - - // Add to user-facing list - g.PlatformIO.Viewports.push_back(viewport); - } - g.Viewports[0]->ClearRequestFlags(); // Clear main viewport flags because UpdatePlatformWindows() won't do it and may not even be called + // Update user-facing viewport list (g.Viewports -> g.PlatformIO.Viewports after filtering out some) + UpdateViewportsEndFrame(); // Sort the window list so that all child windows are after their parent // We cannot do that on FocusWindow() because childs may not exist yet @@ -5178,16 +5163,26 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) SetCurrentWindow(window); } - // Synchronize viewport --> window in case the platform window has been moved or resized from the OS/WM if (window->ViewportOwned) { + // Synchronize viewport -> window in case the platform window has been moved or resized from the OS/WM if (window->Viewport->PlatformRequestMove) window->Pos = window->Viewport->Pos; if (window->Viewport->PlatformRequestResize) window->Size = window->SizeFull = window->Viewport->Size; + // Update common viewport flags + ImGuiViewportFlags viewport_flags = (window->Viewport->Flags) & ~(ImGuiViewportFlags_TopMost | ImGuiViewportFlags_NoTaskBarIcon | ImGuiViewportFlags_NoDecoration); + if (flags & ImGuiWindowFlags_Tooltip) + viewport_flags |= ImGuiViewportFlags_TopMost; + if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsNoTaskBarIcon) != 0 || (flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0) + viewport_flags |= ImGuiViewportFlags_NoTaskBarIcon; + if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsDecoration) == 0 || (flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0) + viewport_flags |= ImGuiViewportFlags_NoDecoration; + // We also tell the back-end that clearing the platform window won't be necessary, as our window is filling the viewport and we have disabled BgAlpha - window->Viewport->Flags |= ImGuiViewportFlags_NoRendererClear; + viewport_flags |= ImGuiViewportFlags_NoRendererClear; + window->Viewport->Flags = viewport_flags; } // Clamp position so window stays visible within its viewport or monitor @@ -7387,8 +7382,7 @@ static ImGuiViewportP* FindViewportHoveredFromPlatformWindowStack(const ImVec2 m return best_candidate; } -// Called in NewFrame() -static void ImGui::UpdateViewports() +static void ImGui::UpdateViewportsNewFrame() { ImGuiContext& g = *GImGui; IM_ASSERT(g.PlatformIO.Viewports.Size <= g.Viewports.Size); @@ -7540,6 +7534,27 @@ static void ImGui::UpdateViewports() IM_ASSERT(g.MouseViewport != NULL); } +// Update user-facing viewport list (g.Viewports -> g.PlatformIO.Viewports after filtering out some) +static void ImGui::UpdateViewportsEndFrame() +{ + ImGuiContext& g = *GImGui; + g.PlatformIO.MainViewport = g.Viewports[0]; + g.PlatformIO.Viewports.resize(0); + for (int i = 0; i < g.Viewports.Size; i++) + { + ImGuiViewportP* viewport = g.Viewports[i]; + viewport->LastPos = viewport->Pos; + if (viewport->LastFrameActive < g.FrameCount || viewport->Size.x <= 0.0f || viewport->Size.y <= 0.0f) + continue; + if (viewport->Window && !IsWindowActiveAndVisible(viewport->Window)) + continue; + if (i > 0) + IM_ASSERT(viewport->Window != NULL); + g.PlatformIO.Viewports.push_back(viewport); + } + g.Viewports[0]->ClearRequestFlags(); // Clear main viewport flags because UpdatePlatformWindows() won't do it and may not even be called +} + // FIXME: We should ideally refactor the system to call this every frame (we currently don't) ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const ImVec2& pos, const ImVec2& size, ImGuiViewportFlags flags) { @@ -7734,19 +7749,6 @@ void ImGui::UpdatePlatformWindows() if (viewport->LastFrameActive < g.FrameCount || viewport->Size.x <= 0 || viewport->Size.y <= 0) continue; - // Update common viewport flags for owned viewports - if (ImGuiWindow* window = viewport->Window) - { - ImGuiViewportFlags flags = viewport->Flags & ~(ImGuiViewportFlags_TopMost | ImGuiViewportFlags_NoTaskBarIcon | ImGuiViewportFlags_NoDecoration); - if (window->Flags & ImGuiWindowFlags_Tooltip) - flags |= ImGuiViewportFlags_TopMost; - if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsNoTaskBarIcon) != 0 || (window->Flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0) - flags |= ImGuiViewportFlags_NoTaskBarIcon; - if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsDecoration) == 0 || (window->Flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0) - flags |= ImGuiViewportFlags_NoDecoration; - viewport->Flags = flags; - } - // Create window bool is_new_platform_window = (viewport->PlatformWindowCreated == false); if (is_new_platform_window) diff --git a/imgui.h b/imgui.h index b0ad4ed4..b0f1dccc 100644 --- a/imgui.h +++ b/imgui.h @@ -989,8 +989,8 @@ enum ImGuiConfigFlags_ // When using viewports it is recommended that your default value for ImGuiCol_WindowBg is opaque (Alpha=1.0) so transition to a viewport won't be noticeable. ImGuiConfigFlags_ViewportsEnable = 1 << 10, // Viewport enable flags (require both ImGuiConfigFlags_PlatformHasViewports + ImGuiConfigFlags_RendererHasViewports set by the respective back-ends) ImGuiConfigFlags_ViewportsNoTaskBarIcon = 1 << 11, // Disable task bars icons for all secondary viewports (will set ImGuiViewportFlags_NoTaskBarIcon on them) - ImGuiConfigFlags_ViewportsNoMerge = 1 << 12, // All floating windows will always create their own viewport and platform window. - ImGuiConfigFlags_ViewportsDecoration = 1 << 13, // FIXME [Broken] Enable platform decoration for all secondary viewports (will not set ImGuiViewportFlags_NoDecoration on them). This currently doesn't behave well in Windows because 1) By default the new window animation get in the way of our transitions, 2) It enable a minimum window size which tends to breaks resizing. You can workaround the later by setting style.WindowMinSize to a bigger value. + ImGuiConfigFlags_ViewportsDecoration = 1 << 12, // FIXME [Broken] Enable platform decoration for all secondary viewports (will not set ImGuiViewportFlags_NoDecoration on them). This currently doesn't behave well in Windows because 1) By default the new window animation get in the way of our transitions, 2) It enable a minimum window size which tends to breaks resizing. You can workaround the later by setting style.WindowMinSize to a bigger value. + ImGuiConfigFlags_ViewportsNoMerge = 1 << 13, // All floating windows will always create their own viewport and platform window. ImGuiConfigFlags_DpiEnableScaleViewports= 1 << 14, // FIXME-DPI: Reposition and resize imgui windows when the DpiScale of a viewport changed (mostly useful for the main viewport hosting other window). Note that resizing the main window itself is up to your application. ImGuiConfigFlags_DpiEnableScaleFonts = 1 << 15, // FIXME-DPI: Request bitmap-scaled fonts to match DpiScale. This is a very low-quality workaround. The correct way to handle DPI is _currently_ to replace the atlas and/or fonts in the Platform_OnChangedViewport callback, but this is all early work in progress. @@ -2217,11 +2217,11 @@ struct ImGuiPlatformIO enum ImGuiViewportFlags_ { ImGuiViewportFlags_None = 0, - ImGuiViewportFlags_NoDecoration = 1 << 0, // Platform Window: Disable platform decorations: title bar, borders, etc. - ImGuiViewportFlags_NoFocusOnAppearing = 1 << 1, // Platform Window: Don't take focus when created. - ImGuiViewportFlags_NoInputs = 1 << 2, // Platform Window: Make mouse pass through so we can drag this window while peaking behind it. - ImGuiViewportFlags_NoTaskBarIcon = 1 << 3, // Platform Window: Disable platform task bar icon (for popups, menus, or all windows if ImGuiConfigFlags_ViewportsNoTaskBarIcons if set) - ImGuiViewportFlags_NoRendererClear = 1 << 4, // Platform Window: Renderer doesn't need to clear the framebuffer ahead. + ImGuiViewportFlags_NoDecoration = 1 << 0, // Platform Window: Disable platform decorations: title bar, borders, etc. (generally set all windows, but if ImGuiConfigFlags_ViewportsDecoration is set we only set this on popups/tooltips) + ImGuiViewportFlags_NoTaskBarIcon = 1 << 1, // Platform Window: Disable platform task bar icon (generally set on popups/tooltips, or all windows if ImGuiConfigFlags_ViewportsNoTaskBarIcon is set) + ImGuiViewportFlags_NoFocusOnAppearing = 1 << 2, // Platform Window: Don't take focus when created. + ImGuiViewportFlags_NoInputs = 1 << 3, // Platform Window: Make mouse pass through so we can drag this window while peaking behind it. + ImGuiViewportFlags_NoRendererClear = 1 << 4, // Platform Window: Renderer doesn't need to clear the framebuffer ahead (because we will fill it entirely). ImGuiViewportFlags_TopMost = 1 << 5 // Platform Window: Display on top (for tooltips only) }; diff --git a/imgui_internal.h b/imgui_internal.h index 151b7a4b..fee712b9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -665,7 +665,7 @@ struct ImGuiViewportP : public ImGuiViewport short PlatformMonitor; bool PlatformWindowCreated; bool PlatformWindowMinimized; - ImGuiWindow* Window; // Set when the viewport is owned by a window + ImGuiWindow* Window; // Set when the viewport is owned by a window (and ImGuiViewportFlags_CanHostOtherWindows is NOT set) ImDrawList* OverlayDrawList; // For convenience, a draw list we can render to that's always rendered last (we use it to draw software mouse cursor when io.MouseDrawCursor is set) ImDrawData DrawDataP; ImDrawDataBuilder DrawDataBuilder; From 4a6f95acc881f09de2835a93273cf725801790e1 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 2 Jan 2019 16:06:58 +0100 Subject: [PATCH 12/14] Viewport: Added Platform_UpdateWindow hook for general purpose: Rework Win32 code to reflect viewport flags changes into Win32 while the window is active. --- examples/imgui_impl_win32.cpp | 65 ++++++++++++++++++++++++++--------- imgui.cpp | 4 +++ imgui.h | 1 + 3 files changed, 53 insertions(+), 17 deletions(-) diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index ef22fa47..fed43afd 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -431,33 +431,38 @@ struct ImGuiViewportDataWin32 ~ImGuiViewportDataWin32() { IM_ASSERT(Hwnd == NULL); } }; +static void ImGui_ImplWin32_GetWin32StyleFromViewportFlags(ImGuiViewportFlags flags, DWORD* out_style, DWORD* out_ex_style) +{ + if (flags & ImGuiViewportFlags_NoDecoration) + *out_style = WS_POPUP; + else + *out_style = WS_OVERLAPPEDWINDOW; + + if (flags & ImGuiViewportFlags_NoTaskBarIcon) + *out_ex_style = WS_EX_TOOLWINDOW; + else + *out_ex_style = WS_EX_APPWINDOW; + + if (flags & ImGuiViewportFlags_TopMost) + *out_ex_style |= WS_EX_TOPMOST; +} + static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport) { ImGuiViewportDataWin32* data = IM_NEW(ImGuiViewportDataWin32)(); viewport->PlatformUserData = data; - bool no_decoration = (viewport->Flags & ImGuiViewportFlags_NoDecoration) != 0; - bool no_task_bar_icon = (viewport->Flags & ImGuiViewportFlags_NoTaskBarIcon) != 0; - if (no_decoration) - { - data->DwStyle = WS_POPUP; - data->DwExStyle = no_task_bar_icon ? WS_EX_TOOLWINDOW : WS_EX_APPWINDOW; - } - else - { - data->DwStyle = WS_OVERLAPPEDWINDOW; - data->DwExStyle = no_task_bar_icon ? WS_EX_TOOLWINDOW : WS_EX_APPWINDOW; - } - if (viewport->Flags & ImGuiViewportFlags_TopMost) - data->DwExStyle |= WS_EX_TOPMOST; + // Select style and parent window + HWND parent_window = g_hWnd; + ImGui_ImplWin32_GetWin32StyleFromViewportFlags(viewport->Flags, &data->DwStyle, &data->DwExStyle); // Create window RECT rect = { (LONG)viewport->Pos.x, (LONG)viewport->Pos.y, (LONG)(viewport->Pos.x + viewport->Size.x), (LONG)(viewport->Pos.y + viewport->Size.y) }; ::AdjustWindowRectEx(&rect, data->DwStyle, FALSE, data->DwExStyle); data->Hwnd = ::CreateWindowEx( - data->DwExStyle, _T("ImGui Platform"), _T("No Title Yet"), data->DwStyle, // Style, class name, window name - rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, // Window area - g_hWnd, NULL, ::GetModuleHandle(NULL), NULL); // Parent window, Menu, Instance, Param + data->DwExStyle, _T("ImGui Platform"), _T("Untitled"), data->DwStyle, // Style, class name, window name + rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, // Window area + parent_window, NULL, ::GetModuleHandle(NULL), NULL); // Parent window, Menu, Instance, Param data->HwndOwned = true; viewport->PlatformRequestResize = false; viewport->PlatformHandle = data->Hwnd; @@ -491,6 +496,31 @@ static void ImGui_ImplWin32_ShowWindow(ImGuiViewport* viewport) ::ShowWindow(data->Hwnd, SW_SHOW); } +static void ImGui_ImplWin32_UpdateWindow(ImGuiViewport* viewport) +{ + // (Optional) Update Win32 style if it changed _after_ creation. + // Generally they won't change unless configuration flags are changed, but advanced uses (such as manually rewriting viewport flags) make this useful. + ImGuiViewportDataWin32* data = (ImGuiViewportDataWin32*)viewport->PlatformUserData; + IM_ASSERT(data->Hwnd != 0); + DWORD new_style; + DWORD new_ex_style; + ImGui_ImplWin32_GetWin32StyleFromViewportFlags(viewport->Flags, &new_style, &new_ex_style); + + // Only reapply the flags that have been changed from our point of view (as other flags are being modified by Windows) + if (data->DwStyle != new_style || data->DwExStyle != new_ex_style) + { + data->DwStyle = new_style; + data->DwExStyle = new_ex_style; + ::SetWindowLong(data->Hwnd, GWL_STYLE, data->DwStyle); + ::SetWindowLong(data->Hwnd, GWL_EXSTYLE, data->DwExStyle); + RECT rect = { (LONG)viewport->Pos.x, (LONG)viewport->Pos.y, (LONG)(viewport->Pos.x + viewport->Size.x), (LONG)(viewport->Pos.y + viewport->Size.y) }; + ::AdjustWindowRectEx(&rect, data->DwStyle, FALSE, data->DwExStyle); // Client to Screen + ::SetWindowPos(data->Hwnd, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); + ::ShowWindow(data->Hwnd, SW_SHOWNA); // This is necessary when we alter the style + viewport->PlatformRequestMove = viewport->PlatformRequestResize = true; + } +} + static ImVec2 ImGui_ImplWin32_GetWindowPos(ImGuiViewport* viewport) { ImGuiViewportDataWin32* data = (ImGuiViewportDataWin32*)viewport->PlatformUserData; @@ -695,6 +725,7 @@ static void ImGui_ImplWin32_InitPlatformInterface() platform_io.Platform_GetWindowMinimized = ImGui_ImplWin32_GetWindowMinimized; platform_io.Platform_SetWindowTitle = ImGui_ImplWin32_SetWindowTitle; platform_io.Platform_SetWindowAlpha = ImGui_ImplWin32_SetWindowAlpha; + platform_io.Platform_UpdateWindow = ImGui_ImplWin32_UpdateWindow; platform_io.Platform_GetWindowDpiScale = ImGui_ImplWin32_GetWindowDpiScale; // FIXME-DPI platform_io.Platform_OnChangedViewport = ImGui_ImplWin32_OnChangedViewport; // FIXME-DPI #if HAS_WIN32_IME diff --git a/imgui.cpp b/imgui.cpp index f18c61aa..681d8210 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7794,6 +7794,10 @@ void ImGui::UpdatePlatformWindows() g.PlatformIO.Platform_SetWindowAlpha(viewport, viewport->Alpha); viewport->LastAlpha = viewport->Alpha; + // Optional, general purpose call to allow the back-end to perform general book-keeping even if things haven't changed. + if (g.PlatformIO.Platform_UpdateWindow) + g.PlatformIO.Platform_UpdateWindow(viewport); + if (is_new_platform_window) { // On startup ensure new platform window don't steal focus (give it a few frames, as nested contents may lead to viewport being created a few frames late) diff --git a/imgui.h b/imgui.h index b0f1dccc..6d7f8dd2 100644 --- a/imgui.h +++ b/imgui.h @@ -2186,6 +2186,7 @@ struct ImGuiPlatformIO bool (*Platform_GetWindowMinimized)(ImGuiViewport* vp); void (*Platform_SetWindowTitle)(ImGuiViewport* vp, const char* title); void (*Platform_SetWindowAlpha)(ImGuiViewport* vp, float alpha); // (Optional) Setup window transparency + void (*Platform_UpdateWindow)(ImGuiViewport* vp); // (Optional) Called in UpdatePlatforms(). Optional hook to allow the platform back-end from doing general book-keeping every frame. void (*Platform_RenderWindow)(ImGuiViewport* vp, void* render_arg); // (Optional) Setup for render void (*Platform_SwapBuffers)(ImGuiViewport* vp, void* render_arg); // (Optional) Call Present/SwapBuffers (platform side) float (*Platform_GetWindowDpiScale)(ImGuiViewport* vp); // (Optional) [BETA] (FIXME-DPI) DPI handling: Return DPI scale for this viewport. 1.0f = 96 DPI. From cfcad42b89a2a8d8e789c10fd186b753a13bfc02 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 2 Jan 2019 18:22:31 +0100 Subject: [PATCH 13/14] Viewport: Win32: Workaround to the fact that ::WindowFromPoint() seems to return Windows using ImGuiViewportFlags_NoInputs / HTTRANSPARENT when dragging nearby the platform title bar. This is to allow using platform decoration. I don't understand this well atm. (#1542) --- examples/imgui_impl_win32.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index fed43afd..b2134b30 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -185,10 +185,11 @@ static void ImGui_ImplWin32_UpdateMousePos() // - This is _ignoring_ viewports with the ImGuiViewportFlags_NoInputs flag (pass-through windows). // - This is _regardless_ of whether another viewport is focused or being dragged from. // If ImGuiBackendFlags_HasMouseHoveredViewport is not set by the back-end, imgui will ignore this field and infer the information by relying on the - // rectangles and last focused time of every viewports it knows about. It will be unaware of other windows that may be sitting between or over your windows. + // rectangles and last focused time of every viewports it knows about. It will be unaware of foreign windows that may be sitting between or over your windows. if (HWND hovered_hwnd = ::WindowFromPoint(mouse_screen_pos)) if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle((void*)hovered_hwnd)) - io.MouseHoveredViewport = viewport->ID; + if ((viewport->Flags & ImGuiViewportFlags_NoInputs) == 0) // FIXME: We still get our NoInputs window with WM_NCHITTEST/HTTRANSPARENT code when decorated? + io.MouseHoveredViewport = viewport->ID; } void ImGui_ImplWin32_NewFrame() From 0cabe4dedfb5a8784ffac3e8f974a63fd0fd8dd3 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 2 Jan 2019 19:29:33 +0100 Subject: [PATCH 14/14] Viewport: Added ImGuiWindowClass / SetNextWindowClass() (concept imported from Docking ImGuiDockFamily), which currently allows to overwrite viewport flags on a per-window basis. Exposed FindViewportByID(). Win32: Support for ParentViewportId. (#1542) --- examples/imgui_impl_win32.cpp | 5 ++++- imgui.cpp | 20 ++++++++++++++++---- imgui.h | 18 +++++++++++++++++- imgui_internal.h | 4 +++- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index b2134b30..9d290fd0 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -454,8 +454,11 @@ static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport) viewport->PlatformUserData = data; // Select style and parent window - HWND parent_window = g_hWnd; ImGui_ImplWin32_GetWin32StyleFromViewportFlags(viewport->Flags, &data->DwStyle, &data->DwExStyle); + HWND parent_window = NULL; + if (viewport->ParentViewportId != 0) + if (ImGuiViewport* parent_viewport = ImGui::FindViewportByID(viewport->ParentViewportId)) + parent_window = (HWND)parent_viewport->PlatformHandle; // Create window RECT rect = { (LONG)viewport->Pos.x, (LONG)viewport->Pos.y, (LONG)(viewport->Pos.x + viewport->Size.x), (LONG)(viewport->Pos.y + viewport->Size.y) }; diff --git a/imgui.cpp b/imgui.cpp index 681d8210..0902ea3b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4982,6 +4982,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { window->SizeContentsExplicit = ImVec2(0.0f, 0.0f); } + window->WindowClass = g.NextWindowData.WindowClass; if (g.NextWindowData.CollapsedCond) SetWindowCollapsed(window, g.NextWindowData.CollapsedVal, g.NextWindowData.CollapsedCond); if (g.NextWindowData.FocusCond) @@ -5180,6 +5181,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsDecoration) == 0 || (flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0) viewport_flags |= ImGuiViewportFlags_NoDecoration; + // We can overwrite viewport flags using ImGuiWindowClass (advanced users) + window->Viewport->ParentViewportId = window->WindowClass.ParentViewportId ? window->WindowClass.ParentViewportId : IMGUI_VIEWPORT_DEFAULT_ID; + if (window->WindowClass.ViewportFlagsOverrideMask) + viewport_flags = (viewport_flags & ~window->WindowClass.ViewportFlagsOverrideMask) | (window->WindowClass.ViewportFlagsOverrideValue & window->WindowClass.ViewportFlagsOverrideMask); + // We also tell the back-end that clearing the platform window won't be necessary, as our window is filling the viewport and we have disabled BgAlpha viewport_flags |= ImGuiViewportFlags_NoRendererClear; window->Viewport->Flags = viewport_flags; @@ -6343,6 +6349,12 @@ void ImGui::SetNextWindowViewport(ImGuiID id) g.NextWindowData.ViewportId = id; } +void ImGui::SetNextWindowClass(const ImGuiWindowClass* window_class) +{ + ImGuiContext& g = *GImGui; + g.NextWindowData.WindowClass = *window_class; +} + // In window space (not screen space!) ImVec2 ImGui::GetContentRegionMax() { @@ -7253,7 +7265,7 @@ ImGuiViewport* ImGui::GetMainViewport() return g.Viewports[0]; } -ImGuiViewportP* ImGui::FindViewportByID(ImGuiID id) +ImGuiViewport* ImGui::FindViewportByID(ImGuiID id) { ImGuiContext& g = *GImGui; for (int n = 0; n < g.Viewports.Size; n++) @@ -7493,7 +7505,7 @@ static void ImGui::UpdateViewportsNewFrame() ImGuiViewportP* viewport_hovered = NULL; if (g.IO.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport) { - viewport_hovered = g.IO.MouseHoveredViewport ? FindViewportByID(g.IO.MouseHoveredViewport) : NULL; + viewport_hovered = g.IO.MouseHoveredViewport ? (ImGuiViewportP*)FindViewportByID(g.IO.MouseHoveredViewport) : NULL; if (viewport_hovered && (viewport_hovered->Flags & ImGuiViewportFlags_NoInputs)) { // Back-end failed at honoring its contract if it returned a viewport with the _NoInputs flag. @@ -7646,7 +7658,7 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window) // Attempt to restore saved viewport id (= window that hasn't been activated yet), try to restore the viewport based on saved 'window->ViewportPos' restored from .ini file if (window->Viewport == NULL && window->ViewportId != 0) { - window->Viewport = FindViewportByID(window->ViewportId); + window->Viewport = (ImGuiViewportP*)FindViewportByID(window->ViewportId); if (window->Viewport == NULL && window->ViewportPos.x != FLT_MAX && window->ViewportPos.y != FLT_MAX) window->Viewport = AddUpdateViewport(window, window->ID, window->ViewportPos, window->Size, ImGuiViewportFlags_None); } @@ -7655,7 +7667,7 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window) if (g.NextWindowData.ViewportCond) { // Code explicitly request a viewport - window->Viewport = FindViewportByID(g.NextWindowData.ViewportId); + window->Viewport = (ImGuiViewportP*)FindViewportByID(g.NextWindowData.ViewportId); window->ViewportId = g.NextWindowData.ViewportId; // Store ID even if Viewport isn't resolved yet. } else if ((flags & ImGuiWindowFlags_ChildWindow) || (flags & ImGuiWindowFlags_ChildMenu)) diff --git a/imgui.h b/imgui.h index 6d7f8dd2..8154df6e 100644 --- a/imgui.h +++ b/imgui.h @@ -114,6 +114,7 @@ struct ImGuiStyle; // Runtime data for styling/colors struct ImGuiTextFilter; // Helper to parse and apply text filters (e.g. "aaaaa[,bbbb][,ccccc]") struct ImGuiTextBuffer; // Helper to hold and append into a text buffer (~string builder) struct ImGuiViewport; // Viewport (generally ~1 per window to output to at the OS level. Need per-platform support to use multiple viewports) +struct ImGuiWindowClass; // Window class (rare/advanced uses: provide hints to the platform back-end via altered viewport flags and parent/child info) // Typedefs and Enums/Flags (declared as int for compatibility with old C++, to allow using as flags and to not pollute the top of this file) // Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists. @@ -276,6 +277,7 @@ namespace ImGui IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most. call before Begin() IMGUI_API void SetNextWindowBgAlpha(float alpha); // set next window background color alpha. helper to easily modify ImGuiCol_WindowBg/ChildBg/PopupBg. you may also use ImGuiWindowFlags_NoBackground. IMGUI_API void SetNextWindowViewport(ImGuiID viewport_id); // set next window viewport + IMGUI_API void SetNextWindowClass(const ImGuiWindowClass* window_class); // set next window class (rare/advanced uses: provide hints to the platform back-end via altered viewport flags and parent/child info) IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects. IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0,0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). @@ -688,6 +690,7 @@ namespace ImGui IMGUI_API void UpdatePlatformWindows(); // call in main loop. will call CreateWindow/ResizeWindow/etc. platform functions for each secondary viewport, and DestroyWindow for each inactive viewport. IMGUI_API void RenderPlatformWindowsDefault(void* platform_arg = NULL, void* renderer_arg = NULL); // call in main loop. will call RenderWindow/SwapBuffers platform functions for each secondary viewport. may be reimplemented by user for custom rendering needs. IMGUI_API void DestroyPlatformWindows(); // call DestroyWindow platform functions for all viewports. call from back-end Shutdown() if you need to close platform windows before imgui shutdown. otherwise will be called by DestroyContext(). + IMGUI_API ImGuiViewport* FindViewportByID(ImGuiID id); // this is a helper for back-ends. IMGUI_API ImGuiViewport* FindViewportByPlatformHandle(void* platform_handle); // this is a helper for back-ends. the type platform_handle is decided by the back-end (e.g. HWND, MyWindow*, GLFWwindow* etc.) } // namespace ImGui @@ -1430,6 +1433,18 @@ struct ImGuiPayload bool IsDelivery() const { return Delivery; } }; +// [BETA] Rarely used / very advanced uses only. Use with SetNextWindowClass() function. +// Provide hints to the platform back-end via altered viewport flags (enable/disable OS decoration, OS task bar icons, etc.) and OS level parent/child relationships. +struct ImGuiWindowClass +{ + ImGuiID ClassId; // User data. 0 = Default class (unclassed) + ImGuiID ParentViewportId; // Hint for the platform back-end. If non-zero, the platform back-end can create a parent<>child relationship between the platform windows. Not conforming back-ends are free to e.g. parent every viewport to the main viewport or not. + ImGuiViewportFlags ViewportFlagsOverrideMask; // Viewport flags to override when a window of this class owns a viewport. This allows you to enforce OS decoration or task bar icon, override the defaults on a per-window basis. + ImGuiViewportFlags ViewportFlagsOverrideValue; // Viewport flags values to override when a window of this class owns a viewport. + + ImGuiWindowClass() { ClassId = 0; ParentViewportId = 0; ViewportFlagsOverrideMask = ViewportFlagsOverrideValue = 0x00; } +}; + //----------------------------------------------------------------------------- // Obsolete functions (Will be removed! Read 'API BREAKING CHANGES' section in imgui.cpp for details) //----------------------------------------------------------------------------- @@ -2235,6 +2250,7 @@ struct ImGuiViewport ImVec2 Size; // Size of viewport in pixel float DpiScale; // 1.0f = 96 DPI = No extra scale ImDrawData* DrawData; // The ImDrawData corresponding to this viewport. Valid after Render() and until the next call to NewFrame(). + ImGuiID ParentViewportId; // (Advanced) 0: no parent. Instruct the platform back-end to setup a parent/child relationship between platform windows. void* RendererUserData; // void* to hold custom data structure for the renderer (e.g. swap chain, frame-buffers etc.) void* PlatformUserData; // void* to hold custom data structure for the OS / platform (e.g. windowing info, render context) @@ -2243,7 +2259,7 @@ struct ImGuiViewport bool PlatformRequestMove; // Platform window requested move (e.g. window was moved by the OS / host window manager, authoritative position will be OS window position) bool PlatformRequestResize; // Platform window requested resize (e.g. window was resized by the OS / host window manager, authoritative size will be OS window size) - ImGuiViewport() { ID = 0; Flags = 0; DpiScale = 0.0f; DrawData = NULL; RendererUserData = PlatformUserData = PlatformHandle = NULL; PlatformRequestClose = PlatformRequestMove = PlatformRequestResize = false; } + ImGuiViewport() { ID = 0; Flags = 0; DpiScale = 0.0f; DrawData = NULL; ParentViewportId = 0; RendererUserData = PlatformUserData = PlatformHandle = NULL; PlatformRequestClose = PlatformRequestMove = PlatformRequestResize = false; } ~ImGuiViewport() { IM_ASSERT(PlatformUserData == NULL && RendererUserData == NULL); } }; diff --git a/imgui_internal.h b/imgui_internal.h index fee712b9..16f5dae1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -714,6 +714,7 @@ struct ImGuiNextWindowData void* SizeCallbackUserData; float BgAlphaVal; ImGuiID ViewportId; + ImGuiWindowClass WindowClass; ImVec2 MenuBarOffsetMinVal; // This is not exposed publicly, so we don't clear it. ImGuiNextWindowData() @@ -733,6 +734,7 @@ struct ImGuiNextWindowData void Clear() { PosCond = SizeCond = ContentSizeCond = CollapsedCond = SizeConstraintCond = FocusCond = BgAlphaCond = ViewportCond = 0; + WindowClass = ImGuiWindowClass(); } }; @@ -1121,6 +1123,7 @@ struct IMGUI_API ImGuiWindow char* Name; ImGuiID ID; // == ImHash(Name) ImGuiWindowFlags Flags, FlagsPreviousFrame; // See enum ImGuiWindowFlags_ + ImGuiWindowClass WindowClass; // Advanced users only. Set with SetNextWindowClass() ImGuiViewportP* Viewport; // Always set in Begin(), only inactive windows may have a NULL value here ImGuiID ViewportId; // We backup the viewport id (since the viewport may disappear or never be created if the window is inactive) ImVec2 ViewportPos; // We backup the viewport position (since the viewport may disappear or never be created if the window is inactive) @@ -1331,7 +1334,6 @@ namespace ImGui IMGUI_API void UpdateMouseMovingWindow(); // Viewports - IMGUI_API ImGuiViewportP* FindViewportByID(ImGuiID id); IMGUI_API void ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale); IMGUI_API void DestroyPlatformWindow(ImGuiViewportP* viewport); IMGUI_API void ShowViewportThumbnails();