diff --git a/TODO.txt b/TODO.txt index 1271d346..43df4daf 100644 --- a/TODO.txt +++ b/TODO.txt @@ -24,7 +24,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - window: increase minimum size of a window with menus or fix the menu rendering so that it doesn't look odd. - window: double-clicking on title bar to minimize isn't consistent, perhaps move to single-click on left-most collapse icon? - window: expose contents size. (#1045) - - window: resize from borders and/or all corners. (#822) + - window: resize from borders: support some form of outer padding to make it easier to grab borders. (#822) - window: GetWindowSize() returns (0,0) when not calculated? (#1045) - window: refactor IsWindowFocused(), merge all three existing variants, add flags, similar to #1382. - window: freeze window flag: if not focused/hovered, return false, render with previous ImDrawList. and/or reduce refresh rate. diff --git a/extra_fonts/README.txt b/extra_fonts/README.txt index 5d41a6bb..2287f6ea 100644 --- a/extra_fonts/README.txt +++ b/extra_fonts/README.txt @@ -1,25 +1,48 @@ - The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' (by Tristan Grimmer) that is used by default. - We embed the font in source code so you can use Dear ImGui without any file system access. - You may also load external .TTF/.OTF files. - The files in this folder are suggested fonts, provided as a convenience. - (Note: .OTF support in stb_truetype.h currently doesn't appear to load every font) +The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' (by Tristan Grimmer) that is used by default. +We embed the font in source code so you can use Dear ImGui without any file system access. +You may also load external .TTF/.OTF files. +The files in this folder are suggested fonts, provided as a convenience. +(Note: .OTF support in stb_truetype.h currently doesn't appear to load every font) - Fonts are rasterized in a single texture at the time of calling either of io.Fonts.GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build(). +Fonts are rasterized in a single texture at the time of calling either of io.Fonts.GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build(). +Also read dear imgui FAQ in imgui.cpp! ---------------------------------- +In this document: + +- Using Icons +- Fonts Loading Instructions +- FreeType rasterizer, Small font sizes +- Building Custom Glyph Ranges +- Remapping Codepoints +- Embedding Fonts in Source Code +- Credits/Licences for fonts included in this folder +- Links, Other fonts + + +--------------------------------------- USING ICONS ---------------------------------- +--------------------------------------- Using an icon font (such as FontAwesome: http://fontawesome.io) is an easy and practical way to use icons in your ImGui application. - A common pattern is to merge the icon font within your main font, so you can refer to the icons directly from your strings without having to change fonts back and forth. - To refer to the icon from your C++ code, you can use headers files created by Juliette Foucaut, at https://github.com/juliettef/IconFontCppHeaders - See Links below for other icons fonts and related tools. + A common pattern is to merge the icon font within your main font, so you can embed icons directly from your strings without + having to change fonts back and forth. + + To refer to the icon UTF-8 codepoints from your C++ code, you may use those headers files created by Juliette Foucaut: + https://github.com/juliettef/IconFontCppHeaders + + The C++11 version of those files uses the u8"" utf-8 encoding syntax + \u + #define ICON_FA_SEARCH u8"\uf002" + The pre-C++11 version has the values directly encoded as utf-8: + #define ICON_FA_SEARCH "\xEF\x80\x82" + + Example: // Merge icons into default tool font #include "IconsFontAwesome.h" ImGuiIO& io = ImGui::GetIO(); io.Fonts->AddFontDefault(); + ImFontConfig config; config.MergeMode = true; static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; @@ -28,10 +51,12 @@ // Usage, e.g. ImGui::Text("%s Search", ICON_FA_SEARCH); + See Links below for other icons fonts and related tools. + ---------------------------------- +--------------------------------------- FONTS LOADING INSTRUCTIONS ---------------------------------- +--------------------------------------- Load default font with: @@ -43,7 +68,7 @@ ImGuiIO& io = ImGui::GetIO(); io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels); - Advanced options: + For advanced options create a ImFontConfig structure and pass it to the AddFont function (it will be copied internally) ImFontConfig config; config.OversampleH = 3; @@ -89,9 +114,23 @@ font->DisplayOffset.y += 1; // Render 1 pixel down ---------------------------------- +--------------------------------------- + FREETYPE RASTERIZER, SMALL FONT SIZES +--------------------------------------- + + Dear Imgui uses stb_truetype.h to rasterize fonts (with optional oversampling). + This technique and implementation are not ideal for fonts rendered at _small sizes_, which may appear a little blurry. + There is an implementation of the ImFontAtlas builder using FreeType that you can use: + + https://github.com/ocornut/imgui_club + + FreeType supports auto-hinting which tends to improve the readability of small fonts. + Note that this code currently creates textures that are unoptimally too large (could be fixed with some work) + + +--------------------------------------- BUILDING CUSTOM GLYPH RANGES ---------------------------------- +--------------------------------------- You can use the ImFontAtlas::GlyphRangesBuilder helper to create glyph ranges based on text input. For exemple: for a game where your script is known, if you can feed your entire script to it and only build the characters the game needs. @@ -105,9 +144,9 @@ io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data); ---------------------------------- +--------------------------------------- REMAPPING CODEPOINTS ---------------------------------- +--------------------------------------- All your strings needs to use UTF-8 encoding. Specifying literal in your source code using a local code page (such as CP-923 for Japanese, or CP-1251 for Cyrillic) will NOT work! In C++11 you can encode a string literal in UTF-8 by using the u8"hello" syntax. Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. @@ -117,9 +156,9 @@ You may also try to remap your local codepage characters to their Unicode codepoint using font->AddRemapChar(), but international users may have problems reading/editing your source code. ---------------------------------- - EMBEDDING FONT IN SOURCE CODE ---------------------------------- +--------------------------------------- + EMBEDDING FONTS IN SOURCE CODE +--------------------------------------- Compile and use 'binary_to_compressed_c.cpp' to create a compressed C style array that you can embed in source code. See the documentation in binary_to_compressed_c.cpp for instruction on how to use the tool. @@ -135,9 +174,9 @@ ImFont* font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(compressed_data_base85, size_pixels, ...); ---------------------------------- - FONT FILES INCLUDED IN THIS FOLDER ---------------------------------- +--------------------------------------- + CREDITS/LICENSES FOR FONTS INCLUDED IN THIS FOLDER +--------------------------------------- Roboto-Medium.ttf Apache License 2.0 @@ -172,9 +211,9 @@ SIL OPEN FONT LICENSE Version 1.1 ---------------------------------- - LINKS & OTHER FONTS ---------------------------------- +--------------------------------------- + LINKS, OTHER FONTS +--------------------------------------- (Icons) Icon fonts https://fortawesome.github.io/Font-Awesome/ @@ -213,3 +252,4 @@ http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html Or use Arial Unicode or other Unicode fonts provided with Windows for full characters coverage (not sure of their licensing). + diff --git a/imgui.cpp b/imgui.cpp index db04e144..24d60b72 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -213,6 +213,10 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2017/12/13 (1.53) - renamed GetItemsLineHeightWithSpacing() to GetFrameHeightWithSpacing(). Kept redirection function (will obsolete). + - 2017/12/13 (1.53) - marked IsRootWindowFocused() as obsolete in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Kept redirection function (will obsolete). + - marked IsRootWindowOrAnyChildFocused() as obsolete in favor of using IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows). Kept redirection function (will obsolete). + - 2017/12/12 (1.53) - renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. Kept redirection enum (will obsolete). - 2017/12/10 (1.53) - removed SetNextWindowContentWidth(), prefer using SetNextWindowContentSize(). Kept redirection function (will obsolete). - 2017/11/27 (1.53) - renamed ImGuiTextBuffer::append() helper to appendf(), appendv() to appendfv(). If you copied the 'Log' demo in your code, it uses appendv() so that needs to be renamed. - 2017/11/18 (1.53) - Style, Begin: removed ImGuiWindowFlags_ShowBorders window flag. Borders are now fully set up in the ImGuiStyle structure (see e.g. style.FrameBorderSize, style.WindowBorderSize). Use ImGui::ShowStyleEditor() to look them up. @@ -220,7 +224,7 @@ - 2017/11/18 (1.53) - Style: removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency. - 2017/11/18 (1.53) - Style: renamed ImGuiCol_ChildWindowBg to ImGuiCol_ChildBg. - 2017/11/18 (1.53) - Style: renamed style.ChildWindowRounding to style.ChildRounding, ImGuiStyleVar_ChildWindowRounding to ImGuiStyleVar_ChildRounding. - - 2017/11/02 (1.53) - marked IsRootWindowOrAnyChildHovered() as obsolete is favor of using IsWindowHovered(ImGuiHoveredFlags_FlattenChilds); + - 2017/11/02 (1.53) - marked IsRootWindowOrAnyChildHovered() as obsolete is favor of using IsWindowHovered(ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows); - 2017/10/24 (1.52) - renamed IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS to IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS for consistency. - 2017/10/20 (1.52) - changed IsWindowHovered() default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it. - 2017/10/20 (1.52) - marked IsItemHoveredRect()/IsMouseHoveringWindow() as obsolete, in favor of using the newly introduced flags for IsItemHovered() and IsWindowHovered(). See https://github.com/ocornut/imgui/issues/1382 for details. @@ -1920,13 +1924,6 @@ static void SetCurrentWindow(ImGuiWindow* window) g.FontSize = window->CalcFontSize(); } -ImGuiWindow* ImGui::GetParentWindow() -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.CurrentWindowStack.Size >= 2); - return g.CurrentWindowStack[(unsigned int)g.CurrentWindowStack.Size - 2]; -} - void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) { ImGuiContext& g = *GImGui; @@ -2042,7 +2039,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) // Test for bounding box overlap, as updated as ItemAdd() if (!window->DC.LastItemRectHoveredRect) return false; - IM_ASSERT((flags & ImGuiHoveredFlags_FlattenChilds) == 0); // Flags not supported by this function + IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0); // Flags not supported by this function // Test if we are hovering the right window (our window could be behind another window) // [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable to use IsItemHovered() after EndChild() itself. @@ -3707,9 +3704,9 @@ void ImGui::EndTooltip() void ImGui::OpenPopupEx(ImGuiID id, bool reopen_existing) { ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; + ImGuiWindow* parent_window = g.CurrentWindow; int current_stack_size = g.CurrentPopupStack.Size; - ImGuiPopupRef popup_ref = ImGuiPopupRef(id, window, window->GetID("##Menus"), g.IO.MousePos); // Tagged as new ref because constructor sets Window to NULL (we are passing the ParentWindow info here) + ImGuiPopupRef popup_ref = ImGuiPopupRef(id, parent_window, parent_window->GetID("##Menus"), g.IO.MousePos); // Tagged as new ref because constructor sets Window to NULL. if (g.OpenPopupStack.Size < current_stack_size + 1) g.OpenPopupStack.push_back(popup_ref); else if (reopen_existing || g.OpenPopupStack[current_stack_size].PopupId != id) @@ -3720,7 +3717,7 @@ void ImGui::OpenPopupEx(ImGuiID id, bool reopen_existing) // When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by CloseInactivePopups(). // This is equivalent to what ClosePopupToLevel() does. if (g.OpenPopupStack[current_stack_size].PopupId == id) - FocusWindow(window); + FocusWindow(parent_window); } } @@ -4366,7 +4363,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, true); // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack - ImGuiWindow* parent_window = first_begin_of_the_frame ? (!g.CurrentWindowStack.empty() ? g.CurrentWindowStack.back() : NULL) : window->ParentWindow; + ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & ImGuiWindowFlags_ChildWindow) && !g.CurrentWindowStack.empty() ? g.CurrentWindowStack.back() : NULL) : window->ParentWindow; IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); // Add to stack @@ -4437,8 +4434,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { // Initialize window->ParentWindow = parent_window; - window->RootWindow = !(flags & ImGuiWindowFlags_ChildWindow) ? window : parent_window->RootWindow; - window->RootNonPopupWindow = !(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) || (flags & ImGuiWindowFlags_Modal) ? window : parent_window->RootNonPopupWindow; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing + window->RootWindow = ((flags & ImGuiWindowFlags_ChildWindow) && parent_window) ? parent_window->RootWindow : window; + window->RootNonPopupWindow = !(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) || (flags & ImGuiWindowFlags_Modal) || (parent_window == NULL) ? window : parent_window->RootNonPopupWindow; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing //window->RootNavWindow = window; //while (window->RootNavWindow->Flags & ImGuiWindowFlags_NavFlattened) // window->RootNavWindow = window->RootNavWindow->ParentWindow; @@ -4584,11 +4581,12 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // This is how we end up with child menus appearing (most-commonly) on the right of the parent menu. IM_ASSERT(window_pos_set_by_api); float horizontal_overlap = style.ItemSpacing.x; // We want some overlap to convey the relative depth of each popup (currently the amount of overlap it is hard-coded to style.ItemSpacing.x, may need to introduce another style value). + ImGuiWindow* parent_menu = g.CurrentWindowStack[g.CurrentWindowStack.Size - 2]; ImRect rect_to_avoid; - if (parent_window->DC.MenuBarAppending) - rect_to_avoid = ImRect(-FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight(), FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight() + parent_window->MenuBarHeight()); + if (parent_menu->DC.MenuBarAppending) + rect_to_avoid = ImRect(-FLT_MAX, parent_menu->Pos.y + parent_menu->TitleBarHeight(), FLT_MAX, parent_menu->Pos.y + parent_menu->TitleBarHeight() + parent_menu->MenuBarHeight()); else - rect_to_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX); + rect_to_avoid = ImRect(parent_menu->Pos.x + horizontal_overlap, -FLT_MAX, parent_menu->Pos.x + parent_menu->Size.x - horizontal_overlap - parent_menu->ScrollbarSizes.x, FLT_MAX); window->PosFloat = FindBestWindowPosForPopup(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid); } else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize) @@ -4681,7 +4679,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) ImRect resize_rect(corner, corner + grip.InnerDir * grip_hover_size); resize_rect.FixInverted(); bool hovered, held; - ButtonBehavior(resize_rect, window->GetID((void*)(intptr_t)resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChilds); + ButtonBehavior(resize_rect, window->GetID((void*)(intptr_t)resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChildren); if (hovered || held) g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE; @@ -4707,7 +4705,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) const float BORDER_APPEAR_TIMER = 0.05f; // Reduce visual noise bool hovered, held; ImRect border_rect = GetBorderRect(window, border_n, grip_hover_size, BORDER_SIZE); - ButtonBehavior(border_rect, window->GetID((void*)(intptr_t)(border_n+4)), &hovered, &held, ImGuiButtonFlags_FlattenChilds); + ButtonBehavior(border_rect, window->GetID((void*)(intptr_t)(border_n+4)), &hovered, &held, ImGuiButtonFlags_FlattenChildren); if ((hovered && g.HoveredIdTimer > BORDER_APPEAR_TIMER) || held) { g.MouseCursor = (border_n & 1) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS; @@ -5461,20 +5459,43 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx) return "Unknown"; } +bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent) +{ + if (window->RootWindow == potential_parent) + return true; + while (window != NULL) + { + if (window == potential_parent) + return true; + window = window->ParentWindow; + } + return false; +} + bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) { IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function ImGuiContext& g = *GImGui; - if (flags & ImGuiHoveredFlags_FlattenChilds) + switch (flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) { + case ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows: if (g.HoveredRootWindow != g.CurrentWindow->RootWindow) return false; - } - else - { + break; + case ImGuiHoveredFlags_RootWindow: + if (g.HoveredWindow != g.CurrentWindow->RootWindow) + return false; + break; + case ImGuiHoveredFlags_ChildWindows: + if (g.HoveredWindow == NULL || !IsWindowChildOf(g.HoveredWindow, g.CurrentWindow)) + return false; + break; + default: if (g.HoveredWindow != g.CurrentWindow) return false; + break; } + if (!IsWindowContentHoverable(g.HoveredRootWindow, flags)) return false; if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) @@ -5483,25 +5504,22 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) return true; } -bool ImGui::IsWindowFocused() -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() - return g.NavWindow == g.CurrentWindow; -} - -bool ImGui::IsRootWindowFocused() +bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) { ImGuiContext& g = *GImGui; IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() - return g.NavWindow == g.CurrentWindow->RootWindow; -} -bool ImGui::IsRootWindowOrAnyChildFocused() -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() - return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow; + switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) + { + case ImGuiFocusedFlags_RootWindow | ImGuiHoveredFlags_ChildWindows: + return g.NavWindow && g.CurrentWindow->RootWindow == g.NavWindow->RootWindow; + case ImGuiFocusedFlags_RootWindow: + return g.CurrentWindow->RootWindow == g.NavWindow; + case ImGuiHoveredFlags_ChildWindows: + return g.NavWindow && IsWindowChildOf(g.NavWindow, g.CurrentWindow); + default: + return g.CurrentWindow == g.NavWindow; + } } float ImGui::GetWindowWidth() @@ -5753,7 +5771,13 @@ float ImGui::GetTextLineHeightWithSpacing() return g.FontSize + g.Style.ItemSpacing.y; } -float ImGui::GetItemsLineHeightWithSpacing() +float ImGui::GetFrameHeight() +{ + ImGuiContext& g = *GImGui; + return g.FontSize + g.Style.FramePadding.y * 2.0f; +} + +float ImGui::GetFrameHeightWithSpacing() { ImGuiContext& g = *GImGui; return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y; @@ -6169,7 +6193,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool flags |= ImGuiButtonFlags_PressedOnClickRelease; ImGuiWindow* backup_hovered_window = g.HoveredWindow; - if ((flags & ImGuiButtonFlags_FlattenChilds) && g.HoveredRootWindow == window) + if ((flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredRootWindow == window) g.HoveredWindow = window; bool pressed = false; @@ -6188,11 +6212,11 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool } } - if ((flags & ImGuiButtonFlags_FlattenChilds) && g.HoveredRootWindow == window) + if ((flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredRootWindow == window) g.HoveredWindow = backup_hovered_window; // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one. - if (hovered && (flags & ImGuiButtonFlags_AllowOverlapMode) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) + if (hovered && (flags & ImGuiButtonFlags_AllowItemOverlap) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) hovered = false; if (hovered) @@ -6649,7 +6673,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // - OpenOnDoubleClick .............. double-click anywhere to open // - OpenOnArrow .................... single-click on arrow to open // - OpenOnDoubleClick|OpenOnArrow .. single-click on arrow or double-click anywhere to open - ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowOverlapMode : 0); + ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowItemOverlap : 0); button_flags |= ImGuiButtonFlags_PressedOnDragDropHold; if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); @@ -6669,7 +6693,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l window->DC.StateStorage->SetInt(id, is_open); } } - if (flags & ImGuiTreeNodeFlags_AllowOverlapMode) + if (flags & ImGuiTreeNodeFlags_AllowItemOverlap) SetItemAllowOverlap(); // Render @@ -6735,7 +6759,7 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags return false; ImGuiID id = window->GetID(label); - bool is_open = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen | (p_open ? ImGuiTreeNodeFlags_AllowOverlapMode : 0), label); + bool is_open = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen | (p_open ? ImGuiTreeNodeFlags_AllowItemOverlap : 0), label); if (p_open) { // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. @@ -8943,12 +8967,6 @@ bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, co return InputTextEx(label, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data); } -static inline float SmallSquareSize() -{ - ImGuiContext& g = *GImGui; - return g.FontSize + g.Style.FramePadding.y * 2.0f; -} - // NB: scalar_format here must be a simple "%xx" format string with no prefix/suffix (unlike the Drag/Slider functions "display_format" argument) bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags) { @@ -8962,7 +8980,7 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data BeginGroup(); PushID(label); - const ImVec2 button_sz = ImVec2(SmallSquareSize(), SmallSquareSize()); + const ImVec2 button_sz = ImVec2(GetFrameHeight(), GetFrameHeight()); if (step_ptr) PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_sz.x + style.ItemInnerSpacing.x)*2)); @@ -9141,7 +9159,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held); bool popup_open = IsPopupOpen(id); - const float arrow_size = SmallSquareSize(); + const float arrow_size = GetFrameHeight(); const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f)); RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING @@ -9441,7 +9459,7 @@ bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_item void ImGui::ListBoxFooter() { - ImGuiWindow* parent_window = GetParentWindow(); + ImGuiWindow* parent_window = GetCurrentWindow()->ParentWindow; const ImRect bb = parent_window->DC.LastItemRect; const ImGuiStyle& style = GetStyle(); @@ -9826,7 +9844,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl ImGuiContext& g = *GImGui; const ImGuiID id = window->GetID(desc_id); - float default_size = SmallSquareSize(); + float default_size = GetFrameHeight(); if (size.x == 0.0f) size.x = default_size; if (size.y == 0.0f) @@ -9949,7 +9967,7 @@ static void ColorPickerOptionsPopup(ImGuiColorEditFlags flags, const float* ref_ ImGuiContext& g = *GImGui; if (allow_opt_picker) { - ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (SmallSquareSize() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function + ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (ImGui::GetFrameHeight() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function ImGui::PushItemWidth(picker_size.x); for (int picker_type = 0; picker_type < 2; picker_type++) { @@ -9989,7 +10007,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; - const float square_sz = SmallSquareSize(); + const float square_sz = GetFrameHeight(); const float w_extra = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x); const float w_items_all = CalcItemWidth() - w_extra; const char* label_display_end = FindRenderedTextEnd(label); @@ -10243,7 +10261,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl int components = (flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4; bool alpha_bar = (flags & ImGuiColorEditFlags_AlphaBar) && !(flags & ImGuiColorEditFlags_NoAlpha); ImVec2 picker_pos = window->DC.CursorPos; - float square_sz = SmallSquareSize(); + float square_sz = GetFrameHeight(); float bars_width = square_sz; // Arbitrary smallish width of Hue/Alpha picking bars float sv_picker_size = ImMax(bars_width * 1, CalcItemWidth() - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x; @@ -10585,7 +10603,7 @@ bool ImGui::SplitterBehavior(ImGuiID id, const ImRect& bb, ImGuiAxis axis, float bool hovered, held; ImRect bb_interact = bb; bb_interact.Expand(axis == ImGuiAxis_Y ? ImVec2(0.0f, hover_extend) : ImVec2(hover_extend, 0.0f)); - ButtonBehavior(bb_interact, id, &hovered, &held, ImGuiButtonFlags_FlattenChilds | ImGuiButtonFlags_AllowOverlapMode); + ButtonBehavior(bb_interact, id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap); if (g.ActiveId != id) SetItemAllowOverlap(); diff --git a/imgui.h b/imgui.h index 7e309af8..3cdec027 100644 --- a/imgui.h +++ b/imgui.h @@ -82,7 +82,8 @@ typedef int ImGuiColorEditFlags; // flags: for ColorEdit*(), ColorPicker*() typedef int ImGuiDragDropFlags; // flags: for *DragDrop*() // enum ImGuiDragDropFlags_ typedef int ImGuiColumnsFlags; // flags: for *Columns*() // enum ImGuiColumnsFlags_ typedef int ImGuiComboFlags; // flags: for BeginCombo() // enum ImGuiComboFlags_ -typedef int ImGuiHoveredFlags; // flags: for IsItemHovered() // enum ImGuiHoveredFlags_ +typedef int ImGuiFocusedFlags; // flags: for IsWindowFocused() // enum ImGuiFocusedFlags_ +typedef int ImGuiHoveredFlags; // flags: for IsItemHovered() etc. // enum ImGuiHoveredFlags_ typedef int ImGuiInputTextFlags; // flags: for InputText*() // enum ImGuiInputTextFlags_ typedef int ImGuiSelectableFlags; // flags: for Selectable() // enum ImGuiSelectableFlags_ typedef int ImGuiTreeNodeFlags; // flags: for TreeNode*(),CollapsingHeader()// enum ImGuiTreeNodeFlags_ @@ -233,9 +234,10 @@ namespace ImGui IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute screen coordinates [0..io.DisplaySize] (useful to work with ImDrawList API) IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute screen coordinates [0..io.DisplaySize] IMGUI_API void AlignTextToFramePadding(); // vertically align/lower upcoming text to FramePadding.y so that it will aligns to upcoming widgets (call if you have text on a line before regular widgets) - IMGUI_API float GetTextLineHeight(); // height of font == GetWindowFontSize() - IMGUI_API float GetTextLineHeightWithSpacing(); // distance (in pixels) between 2 consecutive lines of text == GetWindowFontSize() + GetStyle().ItemSpacing.y - IMGUI_API float GetItemsLineHeightWithSpacing(); // distance (in pixels) between 2 consecutive lines of standard height widgets == GetWindowFontSize() + GetStyle().FramePadding.y*2 + GetStyle().ItemSpacing.y + IMGUI_API float GetTextLineHeight(); // ~ FontSize + IMGUI_API float GetTextLineHeightWithSpacing(); // ~ FontSize + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of text) + IMGUI_API float GetFrameHeight(); // ~ FontSize + style.FramePadding.y * 2 + IMGUI_API float GetFrameHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets) // Columns // You can also use SameLine(pos_x) for simplified columns. The columns API is still work-in-progress and rather lacking. @@ -452,10 +454,8 @@ namespace ImGui IMGUI_API ImVec2 GetItemRectMax(); // " IMGUI_API ImVec2 GetItemRectSize(); // " IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. - IMGUI_API bool IsWindowFocused(); // is current Begin()-ed window focused? - IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags = 0); // is current Begin()-ed window hovered (and typically: not blocked by a popup/modal)? - IMGUI_API bool IsRootWindowFocused(); // is current Begin()-ed root window focused (root = top-most parent of a child, otherwise self)? - IMGUI_API bool IsRootWindowOrAnyChildFocused(); // is current Begin()-ed root window or any of its child (including current window) focused? + IMGUI_API bool IsWindowFocused(ImGuiFocusedFlags flags = 0); // is current window focused? or its root/child, depending on flags. see flags for options. + IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags = 0); // is current window hovered (and typically: not blocked by a popup/modal)? see flags for options. IMGUI_API bool IsAnyWindowHovered(); // is mouse hovering any visible window IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped. IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side. @@ -516,7 +516,6 @@ namespace ImGui // Flags for ImGui::Begin() enum ImGuiWindowFlags_ { - // Default: 0 ImGuiWindowFlags_NoTitleBar = 1 << 0, // Disable title-bar ImGuiWindowFlags_NoResize = 1 << 1, // Disable user resizing with the lower-right grip ImGuiWindowFlags_NoMove = 1 << 2, // Disable user moving the window @@ -547,7 +546,6 @@ enum ImGuiWindowFlags_ // Flags for ImGui::InputText() enum ImGuiInputTextFlags_ { - // Default: 0 ImGuiInputTextFlags_CharsDecimal = 1 << 0, // Allow 0123456789.+-*/ ImGuiInputTextFlags_CharsHexadecimal = 1 << 1, // Allow 0123456789ABCDEFabcdef ImGuiInputTextFlags_CharsUppercase = 1 << 2, // Turn a..z into A..Z @@ -573,7 +571,7 @@ enum ImGuiTreeNodeFlags_ { ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected ImGuiTreeNodeFlags_Framed = 1 << 1, // Full colored frame (e.g. for CollapsingHeader) - ImGuiTreeNodeFlags_AllowOverlapMode = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one + ImGuiTreeNodeFlags_AllowItemOverlap = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes) ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open @@ -585,12 +583,16 @@ enum ImGuiTreeNodeFlags_ //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 11, // FIXME: TODO: Extend hit box horizontally even if not framed //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 12, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog + + // Obsolete names (will be removed) +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + , ImGuiTreeNodeFlags_AllowOverlapMode = ImGuiTreeNodeFlags_AllowItemOverlap +#endif }; // Flags for ImGui::Selectable() enum ImGuiSelectableFlags_ { - // Default: 0 ImGuiSelectableFlags_DontClosePopups = 1 << 0, // Clicking this don't close parent popup window ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Selectable frame can span all columns (text will still fit in current column) ImGuiSelectableFlags_AllowDoubleClick = 1 << 2 // Generate press events on double clicks too @@ -599,23 +601,32 @@ enum ImGuiSelectableFlags_ // Flags for ImGui::BeginCombo() enum ImGuiComboFlags_ { - ImGuiComboFlags_PopupAlignLeft = 1 << 0, // Align the popup toward the left by default - ImGuiComboFlags_HeightSmall = 1 << 1, // Max ~4 items visible. Tip: If you want your combo popup to be a specific size you can use SetNextWindowSizeConstraints() prior to calling BeginCombo() - ImGuiComboFlags_HeightRegular = 1 << 2, // Max ~8 items visible (default) - ImGuiComboFlags_HeightLarge = 1 << 3, // Max ~20 items visible - ImGuiComboFlags_HeightLargest = 1 << 4, // As many fitting items as possible - ImGuiComboFlags_HeightMask_ = ImGuiComboFlags_HeightSmall | ImGuiComboFlags_HeightRegular | ImGuiComboFlags_HeightLarge | ImGuiComboFlags_HeightLargest + ImGuiComboFlags_PopupAlignLeft = 1 << 0, // Align the popup toward the left by default + ImGuiComboFlags_HeightSmall = 1 << 1, // Max ~4 items visible. Tip: If you want your combo popup to be a specific size you can use SetNextWindowSizeConstraints() prior to calling BeginCombo() + ImGuiComboFlags_HeightRegular = 1 << 2, // Max ~8 items visible (default) + ImGuiComboFlags_HeightLarge = 1 << 3, // Max ~20 items visible + ImGuiComboFlags_HeightLargest = 1 << 4, // As many fitting items as possible + ImGuiComboFlags_HeightMask_ = ImGuiComboFlags_HeightSmall | ImGuiComboFlags_HeightRegular | ImGuiComboFlags_HeightLarge | ImGuiComboFlags_HeightLargest +}; + +// Flags for ImGui::IsWindowFocused() +enum ImGuiFocusedFlags_ +{ + ImGuiFocusedFlags_ChildWindows = 1 << 0, // IsWindowFocused(): Return true if any children of the window is focused + ImGuiFocusedFlags_RootWindow = 1 << 1, // IsWindowFocused(): Test from root window (top most parent of the current hierarchy) + ImGuiFocusedFlags_RootAndChildWindows = ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows, }; // Flags for ImGui::IsItemHovered(), ImGui::IsWindowHovered() enum ImGuiHoveredFlags_ { ImGuiHoveredFlags_Default = 0, // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them. - ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 0, // Return true even if a popup window is normally blocking access to this item/window - //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 1, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. - ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 2, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns. - ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 3, // Return true even if the position is overlapped by another window - ImGuiHoveredFlags_FlattenChilds = 1 << 4, // Treat all child windows as the same window (for IsWindowHovered()) + ImGuiHoveredFlags_ChildWindows = 1 << 0, // IsWindowHovered() only: Return true if any children of the window is hovered + ImGuiHoveredFlags_RootWindow = 1 << 1, // IsWindowHovered() only: Test from root window (top most parent of the current hierarchy) + ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 2, // Return true even if a popup window is normally blocking access to this item/window + //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 3, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. + ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 4, // Return true even if an active item is blocking access to this item/window + ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 5, // Return true even if the position is overlapped by another window ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped }; @@ -784,8 +795,8 @@ enum ImGuiMouseCursor_ ImGuiMouseCursor_Arrow = 0, ImGuiMouseCursor_TextInput, // When hovering over InputText, etc. ImGuiMouseCursor_Move, // Unused - ImGuiMouseCursor_ResizeNS, // Unused - ImGuiMouseCursor_ResizeEW, // When hovering over a column + ImGuiMouseCursor_ResizeNS, // When hovering over an horizontal border + ImGuiMouseCursor_ResizeEW, // When hovering over a vertical border or a column ImGuiMouseCursor_ResizeNESW, // When hovering over the bottom-left corner of a window ImGuiMouseCursor_ResizeNWSE, // When hovering over the bottom-right corner of a window ImGuiMouseCursor_Count_ @@ -963,8 +974,10 @@ struct ImGuiIO #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { - static inline void SetNextWindowContentWidth(float width) { ImGui::SetNextWindowContentSize(ImVec2(width, 0.0f)); } // OBSOLETE 1.53+ (nb: original version preserved last Y value set by SetNextWindowContentSize()) - static inline bool IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags = 0) { return IsItemHovered(flags | ImGuiHoveredFlags_FlattenChilds); } // OBSOLETE 1.53+ use flags directly + static inline bool IsRootWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootWindow); } // OBSOLETE 1.53+ + static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); } // OBSOLETE 1.53+ + static inline void SetNextWindowContentWidth(float width) { SetNextWindowContentSize(ImVec2(width, 0.0f)); } // OBSOLETE 1.53+ (nb: original version preserved last Y value set by SetNextWindowContentSize()) + static inline bool IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags = 0) { return IsItemHovered(flags | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows); } // OBSOLETE 1.53+ use flags directly bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE 1.52+. use SetNextWindowSize() instead if you want to set a window size. static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } // OBSOLETE 1.52+ static inline void SetNextWindowPosCenter(ImGuiCond cond = 0) { SetNextWindowPos(ImVec2(GetIO().DisplaySize.x * 0.5f, GetIO().DisplaySize.y * 0.5f), cond, ImVec2(0.5f, 0.5f)); } // OBSOLETE 1.52+ @@ -1273,7 +1286,7 @@ struct ImGuiListClipper int ItemsCount, StepNo, DisplayStart, DisplayEnd; // items_count: Use -1 to ignore (you can call Begin later). Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step). - // items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetItemsLineHeightWithSpacing(). + // items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing(). // If you don't specify an items_height, you NEED to call Step(). If you specify items_height you may call the old Begin()/End() api directly, but prefer calling Step(). ImGuiListClipper(int items_count = -1, float items_height = -1.0f) { Begin(items_count, items_height); } // NB: Begin() initialize every fields (as we allow user to call Begin/End multiple times on a same instance if they want). ~ImGuiListClipper() { IM_ASSERT(ItemsCount == -1); } // Assert if user forgot to call End() or Step() until false. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 589c65bd..770c5193 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1289,7 +1289,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::SliderInt("Lines", &lines, 1, 15); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f)); - ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetItemsLineHeightWithSpacing()*7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar); + ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetFrameHeightWithSpacing()*7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar); for (int line = 0; line < lines; line++) { // Display random stuff (for the sake of this trivial demo we are using basic Button+SameLine. If you want to create your own time line for a real application you may be better off @@ -1721,7 +1721,7 @@ void ImGui::ShowTestWindow(bool* p_open) { ImGuiIO& io = ImGui::GetIO(); ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor); - ImGui::SameLine(); ShowHelpMarker("Request ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via regular GPU rendering will feel more laggy than hardware cursor, but will be more in sync with your other visuals."); + ImGui::SameLine(); ShowHelpMarker("Request ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something)."); ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse); ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard); @@ -1798,18 +1798,38 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::TreePop(); } - if (ImGui::TreeNode("Hovering")) + if (ImGui::TreeNode("Focused & Hovered Test")) { + static bool embed_all_inside_a_child_window = false; + ImGui::Checkbox("Embed everything inside a child window (for additional testing)", &embed_all_inside_a_child_window); + if (embed_all_inside_a_child_window) + ImGui::BeginChild("embeddingchild", ImVec2(0, ImGui::GetFontSize() * 25), true); + + // Testing IsWindowFocused() function with its various flags (note that the flags can be combined) + ImGui::BulletText( + "IsWindowFocused() = %d\n" + "IsWindowFocused(_ChildWindows) = %d\n" + "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n" + "IsWindowFocused(_RootWindow) = %d\n", + ImGui::IsWindowFocused(), + ImGui::IsWindowFocused(ImGuiHoveredFlags_ChildWindows), + ImGui::IsWindowFocused(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow), + ImGui::IsWindowFocused(ImGuiHoveredFlags_RootWindow)); + // Testing IsWindowHovered() function with its various flags (note that the flags can be combined) ImGui::BulletText( "IsWindowHovered() = %d\n" "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n" "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n" - "IsWindowHovered(_FlattenChilds) = %d\n", + "IsWindowHovered(_ChildWindows) = %d\n" + "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n" + "IsWindowHovered(_RootWindow) = %d\n", ImGui::IsWindowHovered(), ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), - ImGui::IsWindowHovered(ImGuiHoveredFlags_FlattenChilds)); + ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows), + ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow), + ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow)); // Testing IsItemHovered() function (because BulletText is an item itself and that would affect the output of IsItemHovered, we pass all lines in a single items to shorten the code) ImGui::Button("ITEM"); @@ -1825,6 +1845,13 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped), ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly)); + ImGui::BeginChild("child", ImVec2(0,50), true); + ImGui::Text("This is another child window for testing IsWindowHovered() flags."); + ImGui::EndChild(); + + if (embed_all_inside_a_child_window) + EndChild(); + ImGui::TreePop(); } @@ -1832,7 +1859,8 @@ void ImGui::ShowTestWindow(bool* p_open) { ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget."); for (int button = 0; button < 3; button++) - ImGui::Text("IsMouseDragging(%d) = %d", button, ImGui::IsMouseDragging(button)); + ImGui::Text("IsMouseDragging(%d):\n w/ default threshold: %d,\n w/ zero threshold: %d\n w/ large threshold: %d", + button, ImGui::IsMouseDragging(button), ImGui::IsMouseDragging(button, 0.0f), ImGui::IsMouseDragging(button, 20.0f)); ImGui::Button("Drag Me"); if (ImGui::IsItemActive()) { @@ -1841,6 +1869,9 @@ void ImGui::ShowTestWindow(bool* p_open) draw_list->PushClipRectFullScreen(); draw_list->AddLine(ImGui::CalcItemRectClosestPoint(io.MousePos, true, -2.0f), io.MousePos, ImColor(ImGui::GetStyle().Colors[ImGuiCol_Button]), 4.0f); draw_list->PopClipRect(); + + // Drag operations gets "unlocked" when the mouse has moved past a certain threshold (the default threshold is stored in io.MouseDragThreshold) + // You can request a lower or higher threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta() ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f); ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0); ImVec2 mouse_delta = io.MouseDelta; @@ -2507,7 +2538,7 @@ struct ExampleAppConsole ImGui::PopStyleVar(); ImGui::Separator(); - ImGui::BeginChild("ScrollingRegion", ImVec2(0, -ImGui::GetStyle().ItemSpacing.y - ImGui::GetItemsLineHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar); // Leave room for 1 separator + 1 InputText + ImGui::BeginChild("ScrollingRegion", ImVec2(0, -ImGui::GetStyle().ItemSpacing.y - ImGui::GetFrameHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar); // Leave room for 1 separator + 1 InputText if (ImGui::BeginPopupContextWindow()) { if (ImGui::Selectable("Clear")) ClearLog(); @@ -2829,7 +2860,7 @@ static void ShowExampleAppLayout(bool* p_open) // right ImGui::BeginGroup(); - ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetItemsLineHeightWithSpacing())); // Leave room for 1 line below us + ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us ImGui::Text("MyObject: %d", selected); ImGui::Separator(); ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "); diff --git a/imgui_internal.h b/imgui_internal.h index 736f1acd..9f7988c6 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -179,12 +179,12 @@ enum ImGuiButtonFlags_ ImGuiButtonFlags_PressedOnClick = 1 << 2, // return true on click (default requires click+release) ImGuiButtonFlags_PressedOnRelease = 1 << 3, // return true on release (default requires click+release) ImGuiButtonFlags_PressedOnDoubleClick = 1 << 4, // return true on double-click (default requires click+release) - ImGuiButtonFlags_FlattenChilds = 1 << 5, // allow interactions even if a child window is overlapping - ImGuiButtonFlags_DontClosePopups = 1 << 6, // disable automatically closing parent popup on press // [UNUSED] - ImGuiButtonFlags_Disabled = 1 << 7, // disable interactions - ImGuiButtonFlags_AlignTextBaseLine = 1 << 8, // vertically align button to match text baseline (ButtonEx() only) - ImGuiButtonFlags_NoKeyModifiers = 1 << 9, // disable interaction if a key modifier is held - ImGuiButtonFlags_AllowOverlapMode = 1 << 10, // require previous frame HoveredId to either match id or be null before being usable + ImGuiButtonFlags_FlattenChildren = 1 << 5, // allow interactions even if a child window is overlapping + ImGuiButtonFlags_AllowItemOverlap = 1 << 6, // require previous frame HoveredId to either match id or be null before being usable, use along with SetItemAllowOverlap() + ImGuiButtonFlags_DontClosePopups = 1 << 7, // disable automatically closing parent popup on press // [UNUSED] + ImGuiButtonFlags_Disabled = 1 << 8, // disable interactions + ImGuiButtonFlags_AlignTextBaseLine = 1 << 9, // vertically align button to match text baseline (ButtonEx() only) + ImGuiButtonFlags_NoKeyModifiers = 1 << 10, // disable interaction if a key modifier is held ImGuiButtonFlags_NoHoldingActiveID = 1 << 11, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) ImGuiButtonFlags_PressedOnDragDropHold = 1 << 12 // press when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers) }; @@ -772,7 +772,7 @@ struct IMGUI_API ImGuiWindow ImGuiStorage StateStorage; float FontWindowScale; // Scale multiplier per-window ImDrawList* DrawList; - ImGuiWindow* ParentWindow; // Immediate parent in the window stack *regardless* of whether this window is a child window or not) + ImGuiWindow* ParentWindow; // If we are a child window, this is pointing to our parent. ImGuiWindow* RootWindow; // Generally point to ourself. If we are a child window, this is pointing to the first non-child parent window. ImGuiWindow* RootNonPopupWindow; // Generally point to ourself. Used to display TitleBgActive color and for selecting which window to use for NavWindowing @@ -826,11 +826,11 @@ namespace ImGui // - You are calling ImGui functions after ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal. inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; } inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; } - IMGUI_API ImGuiWindow* GetParentWindow(); IMGUI_API ImGuiWindow* FindWindowByName(const char* name); IMGUI_API void FocusWindow(ImGuiWindow* window); IMGUI_API void BringWindowToFront(ImGuiWindow* window); IMGUI_API void BringWindowToBack(ImGuiWindow* window); + IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent); IMGUI_API void Initialize();