From f10bbbb85190eb9fe2529480eeff8a7b899968fa Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Jun 2015 07:57:45 -0600 Subject: [PATCH 01/25] Minor comment fix (#248) --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 26958776..314d0009 100644 --- a/imgui.h +++ b/imgui.h @@ -703,7 +703,7 @@ struct ImGuiIO ImVec2 MouseClickedPos[5]; // Position at time of clicking float MouseClickedTime[5]; // Time of last click (used to figure out double-click) bool MouseDoubleClicked[5]; // Has mouse button been double-clicked? - bool MouseReleased[5]; // Mouse button went from !Down to Down + bool MouseReleased[5]; // Mouse button went from Down to !Down bool MouseDownOwned[5]; // Track if button was clicked inside a window. We don't request mouse capture from the application if click started outside ImGui bounds. float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked) float MouseDownDurationPrev[5]; // Previous time the mouse button has been down From bce495c5813898a4eae503ac02fe8a2d353bdc19 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 23 Jun 2015 10:02:56 -0600 Subject: [PATCH 02/25] Added BeginPopupModal() with actual modal behaviour (WIP api) (#249) --- imgui.cpp | 43 +++++++++++++++++++++++++++++++++++++++---- imgui.h | 10 ++++++---- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d0568bcd..93f996ab 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -548,6 +548,7 @@ static bool CloseWindowButton(bool* p_opened = NULL); static void FocusWindow(ImGuiWindow* window); static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs); static void CloseInactivePopups(); +static ImGuiWindow* GetFrontMostModalRootWindow(); static void SetWindowScrollY(ImGuiWindow* window, float scroll_y); // Helpers: String @@ -2149,6 +2150,9 @@ void ImGui::NewFrame() g.HoveredRootWindow = g.HoveredWindow->RootWindow; else g.HoveredRootWindow = FindHoveredWindow(g.IO.MousePos, true); + if (ImGuiWindow* modal_window = GetFrontMostModalRootWindow()) + if (g.HoveredRootWindow != modal_window) + g.HoveredRootWindow = g.HoveredWindow = NULL; // Are we using inputs? Tell user so they can capture/discard the inputs away from the rest of their application. // When clicking outside of a window we assume the click is owned by the application and won't request capture. @@ -2372,7 +2376,7 @@ void ImGui::Render() g.MovedWindow = g.HoveredWindow; SetActiveId(g.HoveredRootWindow->MoveID, g.HoveredRootWindow); } - else if (g.FocusedWindow != NULL) + else if (g.FocusedWindow != NULL && GetFrontMostModalRootWindow() == NULL) { // Clicking on void disable focus FocusWindow(NULL); @@ -3149,6 +3153,16 @@ static void CloseInactivePopups() g.OpenedPopupStack.resize(n); } +static ImGuiWindow* GetFrontMostModalRootWindow() +{ + ImGuiState& g = *GImGui; + if (!g.OpenedPopupStack.empty()) + if (ImGuiWindow* front_most_popup = g.OpenedPopupStack.back().Window) + if (front_most_popup->Flags & ImGuiWindowFlags_Modal) + return front_most_popup; + return NULL; +} + static void ClosePopupToLevel(int remaining) { ImGuiState& g = *GImGui; @@ -3220,12 +3234,33 @@ bool ImGui::BeginPopup(const char* str_id) return BeginPopupEx(str_id, ImGuiWindowFlags_ShowBorders); } +bool ImGui::BeginPopupModal(const char* name, ImGuiWindowFlags extra_flags) +{ + ImGuiState& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + const ImGuiID id = window->GetID(name); + if (!IsPopupOpen(id)) + { + ClearSetNextWindowData(); // We behave like Begin() and need to consume those values + return false; + } + + ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoSavedSettings; + bool opened = ImGui::Begin(name, NULL, ImVec2(0.0f, 0.0f), -1.0f, flags); + if (!opened) // Opened can be 'false' when the popup is completely clipped (e.g. zero size display) + ImGui::EndPopup(); + + return opened; +} + void ImGui::EndPopup() { - IM_ASSERT(GetCurrentWindow()->Flags & ImGuiWindowFlags_Popup); + ImGuiWindow* window = GetCurrentWindow(); + IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup); IM_ASSERT(GImGui->CurrentPopupStack.size() > 0); ImGui::End(); - ImGui::PopStyleVar(); + if (!(window->Flags & ImGuiWindowFlags_Modal)) + ImGui::PopStyleVar(); } bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button) @@ -3611,7 +3646,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ window->SizeContents.y += window->ScrollY; // Hide popup/tooltip window when first appearing while we measure size (because we recycle them) - if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && !window_was_visible) + if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && (flags & ImGuiWindowFlags_AlwaysAutoResize) && !window_was_visible) { window->HiddenFrames = 1; if (!window_size_set_by_api) diff --git a/imgui.h b/imgui.h index 314d0009..01d7ddb4 100644 --- a/imgui.h +++ b/imgui.h @@ -171,9 +171,10 @@ namespace ImGui // Popup IMGUI_API void OpenPopup(const char* str_id); // mark popup as open. popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). close childs popups if any. will close popup when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. IMGUI_API bool BeginPopup(const char* str_id); // return true if popup if opened and start outputting to it. only call EndPopup() if BeginPopup() returned true! - IMGUI_API bool BeginPopupContextItem(const char* str_id, int mouse_button = 1); // open and begin popup when clicked on last item - IMGUI_API bool BeginPopupContextWindow(bool also_over_items = true, const char* str_id = NULL, int mouse_button = 1); // open and begin popup when clicked on current window - IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, int mouse_button = 1); // open and begin popup when clicked in void (no window) + IMGUI_API bool BeginPopupModal(const char* name, ImGuiWindowFlags extra_flags = 0); + IMGUI_API bool BeginPopupContextItem(const char* str_id, int mouse_button = 1); // helper to open and begin popup when clicked on last item + IMGUI_API bool BeginPopupContextWindow(bool also_over_items = true, const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked on current window + IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked in void (no window) IMGUI_API void EndPopup(); IMGUI_API void CloseCurrentPopup(); // close the popup we have begin-ed into. clicking on a MenuItem or Selectable automatically close the current popup. @@ -428,7 +429,8 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_ComboBox = 1 << 23, // Don't use! For internal use by ComboBox() ImGuiWindowFlags_Tooltip = 1 << 24, // Don't use! For internal use by BeginTooltip() ImGuiWindowFlags_Popup = 1 << 25, // Don't use! For internal use by BeginPopup() - ImGuiWindowFlags_ChildMenu = 1 << 26 // Don't use! For internal use by BeginMenu() + ImGuiWindowFlags_Modal = 1 << 26, // Don't use! For internal use by BeginPopupModal() + ImGuiWindowFlags_ChildMenu = 1 << 27 // Don't use! For internal use by BeginMenu() }; // Flags for ImGui::InputText() From 8c790a32344812028faf805768bc2853f13a12e4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 23 Jun 2015 11:08:19 -0600 Subject: [PATCH 03/25] BeginPopupModal() can have an optional close-window button (#249) --- imgui.cpp | 11 ++++++++--- imgui.h | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 93f996ab..9c074dd7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3234,7 +3234,7 @@ bool ImGui::BeginPopup(const char* str_id) return BeginPopupEx(str_id, ImGuiWindowFlags_ShowBorders); } -bool ImGui::BeginPopupModal(const char* name, ImGuiWindowFlags extra_flags) +bool ImGui::BeginPopupModal(const char* name, bool* p_opened, ImGuiWindowFlags extra_flags) { ImGuiState& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -3246,9 +3246,14 @@ bool ImGui::BeginPopupModal(const char* name, ImGuiWindowFlags extra_flags) } ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoSavedSettings; - bool opened = ImGui::Begin(name, NULL, ImVec2(0.0f, 0.0f), -1.0f, flags); - if (!opened) // Opened can be 'false' when the popup is completely clipped (e.g. zero size display) + bool opened = ImGui::Begin(name, p_opened, ImVec2(0.0f, 0.0f), -1.0f, flags); + if (!opened || (p_opened && !*p_opened)) // Opened can be 'false' when the popup is completely clipped (e.g. zero size display) + { ImGui::EndPopup(); + if (opened) + ClosePopup(id); + return false; + } return opened; } diff --git a/imgui.h b/imgui.h index 01d7ddb4..26deb824 100644 --- a/imgui.h +++ b/imgui.h @@ -171,8 +171,8 @@ namespace ImGui // Popup IMGUI_API void OpenPopup(const char* str_id); // mark popup as open. popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). close childs popups if any. will close popup when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. IMGUI_API bool BeginPopup(const char* str_id); // return true if popup if opened and start outputting to it. only call EndPopup() if BeginPopup() returned true! - IMGUI_API bool BeginPopupModal(const char* name, ImGuiWindowFlags extra_flags = 0); - IMGUI_API bool BeginPopupContextItem(const char* str_id, int mouse_button = 1); // helper to open and begin popup when clicked on last item + IMGUI_API bool BeginPopupModal(const char* name, bool* p_opened = NULL, ImGuiWindowFlags extra_flags = 0); // modal dialog (can't close them by clicking outside) + IMGUI_API bool BeginPopupContextItem(const char* str_id, int mouse_button = 1); // helper to open and begin popup when clicked on last item IMGUI_API bool BeginPopupContextWindow(bool also_over_items = true, const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked on current window IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked in void (no window) IMGUI_API void EndPopup(); From fe17f6e73527929b01c3228a11f30505b88c88db Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 23 Jun 2015 12:34:15 -0600 Subject: [PATCH 04/25] Added modal window darkening of previous windows (#249) --- imgui.cpp | 19 +++++++++++++++++++ imgui.h | 1 + 2 files changed, 20 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 9c074dd7..b090f489 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -651,6 +651,7 @@ ImGuiStyle::ImGuiStyle() Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); Colors[ImGuiCol_TooltipBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f); + Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); } // Statically allocated font atlas. This is merely a maneuver to keep ImFontAtlas definition at the bottom of the .h file (otherwise it'd be inside ImGuiIO) @@ -1297,6 +1298,7 @@ struct ImGuiState // Render ImVector RenderDrawLists[3]; + float ModalWindowDarkeningRatio; // Mouse cursor ImGuiMouseCursor MouseCursor; @@ -1377,6 +1379,7 @@ struct ImGuiState memset(Tooltip, 0, sizeof(Tooltip)); PrivateClipboard = NULL; + ModalWindowDarkeningRatio = 0.0f; MouseCursor = ImGuiMouseCursor_Arrow; LogEnabled = false; @@ -2150,9 +2153,17 @@ void ImGui::NewFrame() g.HoveredRootWindow = g.HoveredWindow->RootWindow; else g.HoveredRootWindow = FindHoveredWindow(g.IO.MousePos, true); + if (ImGuiWindow* modal_window = GetFrontMostModalRootWindow()) + { + g.ModalWindowDarkeningRatio = ImMin(g.ModalWindowDarkeningRatio + g.IO.DeltaTime * 6.0f, 1.0f); if (g.HoveredRootWindow != modal_window) g.HoveredRootWindow = g.HoveredWindow = NULL; + } + else + { + g.ModalWindowDarkeningRatio = 0.0f; + } // Are we using inputs? Tell user so they can capture/discard the inputs away from the rest of their application. // When clicking outside of a window we assume the click is owned by the application and won't request capture. @@ -3799,6 +3810,13 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ if (!window->Collapsed && !window->SkipItems) window->ScrollY = ImMin(window->ScrollY, ImMax(0.0f, window->SizeContents.y - window->SizeFull.y)); + // Modal window darkens what is behind them + if ((flags & ImGuiWindowFlags_Modal) != 0 && window == GetFrontMostModalRootWindow()) + { + ImVec4 fullscreen_rect = GetVisibleRect(); + window->DrawList->AddRectFilled(ImVec2(fullscreen_rect.x, fullscreen_rect.y), ImVec2(fullscreen_rect.z, fullscreen_rect.w), window->Color(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); + } + // Draw window + handle manual resize ImRect title_bar_rect = window->TitleBarRect(); const float window_rounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding; @@ -4392,6 +4410,7 @@ const char* ImGui::GetStyleColName(ImGuiCol idx) case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered"; case ImGuiCol_TextSelectedBg: return "TextSelectedBg"; case ImGuiCol_TooltipBg: return "TooltipBg"; + case ImGuiCol_ModalWindowDarkening: return "ModalWindowDarkening"; } IM_ASSERT(0); return "Unknown"; diff --git a/imgui.h b/imgui.h index 26deb824..8d6baf25 100644 --- a/imgui.h +++ b/imgui.h @@ -528,6 +528,7 @@ enum ImGuiCol_ ImGuiCol_PlotHistogramHovered, ImGuiCol_TextSelectedBg, ImGuiCol_TooltipBg, + ImGuiCol_ModalWindowDarkening, // darken entire screen when a modal window is active ImGuiCol_COUNT }; From a4cd585f54c0e3286235b8efe3e033b7820f9bda Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 23 Jun 2015 12:47:38 -0600 Subject: [PATCH 05/25] Reorganized demo window --- imgui.cpp | 235 +++++++++++++++++++++++++++++------------------------- 1 file changed, 128 insertions(+), 107 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b090f489..a081b1b5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10899,81 +10899,6 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::TreePop(); } - if (ImGui::TreeNode("Popup, Menus")) - { - ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it."); - - static int selected_fish = -1; - const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" }; - static bool toggles[] = { true, false, false, false, false }; - - if (ImGui::Button("Select..")) - ImGui::OpenPopup("select"); - ImGui::SameLine(); - ImGui::Text(selected_fish == -1 ? "" : names[selected_fish]); - if (ImGui::BeginPopup("select")) - { - ImGui::Text("Aquarium"); - ImGui::Separator(); - for (int i = 0; i < IM_ARRAYSIZE(names); i++) - if (ImGui::Selectable(names[i])) - selected_fish = i; - ImGui::EndPopup(); - } - - if (ImGui::Button("Toggle..")) - ImGui::OpenPopup("toggle"); - if (ImGui::BeginPopup("toggle")) - { - for (int i = 0; i < IM_ARRAYSIZE(names); i++) - ImGui::MenuItem(names[i], "", &toggles[i]); - if (ImGui::BeginMenu("Sub-menu")) - { - ImGui::MenuItem("Click me"); - ImGui::EndMenu(); - } - - ImGui::Separator(); - ImGui::Text("Tooltip here"); - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("I am a tooltip over a popup"); - - if (ImGui::Button("Stacked Popup")) - ImGui::OpenPopup("another popup"); - if (ImGui::BeginPopup("another popup")) - { - for (int i = 0; i < IM_ARRAYSIZE(names); i++) - ImGui::MenuItem(names[i], "", &toggles[i]); - if (ImGui::BeginMenu("Sub-menu")) - { - ImGui::MenuItem("Click me"); - ImGui::EndMenu(); - } - ImGui::EndPopup(); - } - ImGui::EndPopup(); - } - - if (ImGui::Button("Popup Menu..")) - ImGui::OpenPopup("popup from button"); - if (ImGui::BeginPopup("popup from button")) - { - ShowExampleMenuFile(); - ImGui::EndPopup(); - } - - static float value = 0.5f; - ImGui::Text("Value = %.3f (Context menu, right-click here)", value); - if (ImGui::BeginPopupContextItem("item context menu")) - { - if (ImGui::Selectable("Set to zero")) value = 0.0f; - if (ImGui::Selectable("Set to PI")) value = PI; - ImGui::EndPopup(); - } - - ImGui::TreePop(); - } - if (ImGui::TreeNode("Filtered Text Input")) { static char buf1[64] = ""; ImGui::InputText("default", buf1, 64); @@ -11258,6 +11183,46 @@ void ImGui::ShowTestWindow(bool* opened) if (ImGui::CollapsingHeader("Layout")) { + if (ImGui::TreeNode("Child regions")) + { + ImGui::Text("Without border"); + static int line = 50; + bool goto_line = ImGui::Button("Goto"); + ImGui::SameLine(); + ImGui::PushItemWidth(100); + goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue); + ImGui::PopItemWidth(); + ImGui::BeginChild("Sub1", ImVec2(ImGui::GetWindowWidth() * 0.5f,300)); + for (int i = 0; i < 100; i++) + { + ImGui::Text("%04d: scrollable region", i); + if (goto_line && line == i) + ImGui::SetScrollPosHere(); + } + if (goto_line && line >= 100) + ImGui::SetScrollPosHere(); + ImGui::EndChild(); + + ImGui::SameLine(); + + ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, 5.0f); + ImGui::BeginChild("Sub2", ImVec2(0,300), true); + ImGui::Text("With border"); + ImGui::Columns(2); + for (int i = 0; i < 100; i++) + { + if (i == 50) + ImGui::NextColumn(); + char buf[32]; + sprintf(buf, "%08x", i*5731); + ImGui::Button(buf); + } + ImGui::EndChild(); + ImGui::PopStyleVar(); + + ImGui::TreePop(); + } + if (ImGui::TreeNode("Widgets Alignment")) { static float f = 0.0f; @@ -11428,42 +11393,98 @@ void ImGui::ShowTestWindow(bool* opened) } } - if (ImGui::CollapsingHeader("Child regions")) + if (ImGui::CollapsingHeader("Popups & Modal windows")) { - ImGui::Text("Without border"); - static int line = 50; - bool goto_line = ImGui::Button("Goto"); - ImGui::SameLine(); - ImGui::PushItemWidth(100); - goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue); - ImGui::PopItemWidth(); - ImGui::BeginChild("Sub1", ImVec2(ImGui::GetWindowWidth() * 0.5f,300)); - for (int i = 0; i < 100; i++) - { - ImGui::Text("%04d: scrollable region", i); - if (goto_line && line == i) - ImGui::SetScrollPosHere(); - } - if (goto_line && line >= 100) - ImGui::SetScrollPosHere(); - ImGui::EndChild(); + ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it."); - ImGui::SameLine(); - - ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, 5.0f); - ImGui::BeginChild("Sub2", ImVec2(0,300), true); - ImGui::Text("With border"); - ImGui::Columns(2); - for (int i = 0; i < 100; i++) + if (ImGui::TreeNode("Popups")) { - if (i == 50) - ImGui::NextColumn(); - char buf[32]; - sprintf(buf, "%08x", i*5731); - ImGui::Button(buf); + static int selected_fish = -1; + const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" }; + static bool toggles[] = { true, false, false, false, false }; + + if (ImGui::Button("Select..")) + ImGui::OpenPopup("select"); + ImGui::SameLine(); + ImGui::Text(selected_fish == -1 ? "" : names[selected_fish]); + if (ImGui::BeginPopup("select")) + { + ImGui::Text("Aquarium"); + ImGui::Separator(); + for (int i = 0; i < IM_ARRAYSIZE(names); i++) + if (ImGui::Selectable(names[i])) + selected_fish = i; + ImGui::EndPopup(); + } + + if (ImGui::Button("Toggle..")) + ImGui::OpenPopup("toggle"); + if (ImGui::BeginPopup("toggle")) + { + for (int i = 0; i < IM_ARRAYSIZE(names); i++) + ImGui::MenuItem(names[i], "", &toggles[i]); + if (ImGui::BeginMenu("Sub-menu")) + { + ImGui::MenuItem("Click me"); + ImGui::EndMenu(); + } + + ImGui::Separator(); + ImGui::Text("Tooltip here"); + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("I am a tooltip over a popup"); + + if (ImGui::Button("Stacked Popup")) + ImGui::OpenPopup("another popup"); + if (ImGui::BeginPopup("another popup")) + { + for (int i = 0; i < IM_ARRAYSIZE(names); i++) + ImGui::MenuItem(names[i], "", &toggles[i]); + if (ImGui::BeginMenu("Sub-menu")) + { + ImGui::MenuItem("Click me"); + ImGui::EndMenu(); + } + ImGui::EndPopup(); + } + ImGui::EndPopup(); + } + + if (ImGui::Button("Popup Menu..")) + ImGui::OpenPopup("popup from button"); + if (ImGui::BeginPopup("popup from button")) + { + ShowExampleMenuFile(); + ImGui::EndPopup(); + } + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Context menus")) + { + static float value = 0.5f; + ImGui::Text("Value = %.3f (<-- right-click here)", value); + if (ImGui::BeginPopupContextItem("item context menu")) + { + if (ImGui::Selectable("Set to zero")) value = 0.0f; + if (ImGui::Selectable("Set to PI")) value = PI; + ImGui::EndPopup(); + } + + static ImVec4 color = ImColor(1.0f, 0.0f, 1.0f, 1.0f); + ImGui::ColorButton(color); + if (ImGui::BeginPopupContextItem("color context menu")) + { + ImGui::Text("Edit color"); + ImGui::ColorEdit3("##edit", (float*)&color); + if (ImGui::Button("Close")) + ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); + } + ImGui::SameLine(); ImGui::Text("(<-- right-click here)"); + + ImGui::TreePop(); } - ImGui::EndChild(); - ImGui::PopStyleVar(); } if (ImGui::CollapsingHeader("Columns")) From f0311b643a7f5d18b4ba955a31cca825e18575db Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 23 Jun 2015 13:22:37 -0600 Subject: [PATCH 06/25] Added modal dialog example (#249) --- imgui.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a081b1b5..b0182e19 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11395,10 +11395,10 @@ void ImGui::ShowTestWindow(bool* opened) if (ImGui::CollapsingHeader("Popups & Modal windows")) { - ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it."); - if (ImGui::TreeNode("Popups")) { + ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it."); + static int selected_fish = -1; const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" }; static bool toggles[] = { true, false, false, false, false }; @@ -11485,6 +11485,31 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::TreePop(); } + + if (ImGui::TreeNode("Modals")) + { + ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside the window."); + + if (ImGui::Button("Delete")) + ImGui::OpenPopup("Delete?"); + if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse)) + { + ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n"); + ImGui::Separator(); + + static bool dont_ask_me_next_time = false; + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0)); + ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time); + ImGui::PopStyleVar(); + + if (ImGui::Button("OK", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); } + ImGui::SameLine(); + if (ImGui::Button("Cancel", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); } + ImGui::EndPopup(); + } + + ImGui::TreePop(); + } } if (ImGui::CollapsingHeader("Columns")) From 0f38a53d281a5ebd8ed390b75deca3c107ac78b2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 23 Jun 2015 13:58:47 -0600 Subject: [PATCH 07/25] Added stacked modal windows example (#249) --- imgui.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index b0182e19..eca97695 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11490,7 +11490,7 @@ void ImGui::ShowTestWindow(bool* opened) { ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside the window."); - if (ImGui::Button("Delete")) + if (ImGui::Button("Delete..")) ImGui::OpenPopup("Delete?"); if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse)) { @@ -11508,6 +11508,27 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::EndPopup(); } + if (ImGui::Button("Stacked modals..")) + ImGui::OpenPopup("Stacked 1"); + if (ImGui::BeginPopupModal("Stacked 1")) + { + ImGui::Text("Hello from Stacked The First"); + + if (ImGui::Button("Another one..")) + ImGui::OpenPopup("Stacked 2"); + if (ImGui::BeginPopupModal("Stacked 2")) + { + ImGui::Text("Hello from Stacked The Second"); + if (ImGui::Button("Close")) + ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); + } + + if (ImGui::Button("Close")) + ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); + } + ImGui::TreePop(); } } From 2a041cfbe17314d4d70b703183ca54bc14ef3659 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 23 Jun 2015 14:13:22 -0600 Subject: [PATCH 08/25] Added GetGlyphRangesCyrillic() helper (#237) --- imgui.cpp | 18 ++++++++++++++++-- imgui.h | 1 + 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index eca97695..3c360aaf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -17,7 +17,7 @@ - Why is my text output blurry? - How can I load a different font than the default? - How can I load multiple fonts? - - How can I display and input Chinese, Japanese, Korean characters? + - How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic? - ISSUES & TODO-LIST - CODE - SAMPLE CODE @@ -309,7 +309,8 @@ // the first loaded font gets used by default // use ImGui::PushFont()/ImGui::PopFont() to change the font at runtime - Q: How can I render and input Chinese, Japanese, Korean characters? + + Q: How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic? A: When loading a font, pass custom Unicode ranges to specify the glyphs to load. ImGui will support UTF-8 encoding across the board. Character input depends on you passing the right character code to io.AddInputCharacter(). The example applications do that. @@ -9737,6 +9738,19 @@ const ImWchar* ImFontAtlas::GetGlyphRangesJapanese() return &ranges[0]; } +const ImWchar* ImFontAtlas::GetGlyphRangesCyrillic() +{ + static const ImWchar ranges[] = + { + 0x0020, 0x00FF, // Basic Latin + Latin Supplement + 0x0400, 0x052F, // Cyrillic + Cyrillic Supplement + 0x2DE0, 0x2DFF, // Cyrillic Extended-A + 0xA640, 0xA69F, // Cyrillic Extended-B + 0, + }; + return &ranges[0]; +} + void ImFont::BuildLookupTable() { int max_codepoint = 0; diff --git a/imgui.h b/imgui.h index 8d6baf25..b0b5914d 100644 --- a/imgui.h +++ b/imgui.h @@ -1089,6 +1089,7 @@ struct ImFontAtlas IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin IMGUI_API const ImWchar* GetGlyphRangesJapanese(); // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs IMGUI_API const ImWchar* GetGlyphRangesChinese(); // Japanese + full set of about 21000 CJK Unified Ideographs + IMGUI_API const ImWchar* GetGlyphRangesCyrillic(); // Default + about 400 Cyrillic characters // Members // (Access texture data via GetTexData*() calls which will setup a default font for you.) From 06ed9257ef7adfd71fc788737b881e6e836af515 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 23 Jun 2015 14:28:11 -0600 Subject: [PATCH 09/25] Modal windows centered when appearing (#249) --- imgui.cpp | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3c360aaf..5b46fafc 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3663,12 +3663,15 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ window->SizeContents.y += window->ScrollY; // Hide popup/tooltip window when first appearing while we measure size (because we recycle them) - if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && (flags & ImGuiWindowFlags_AlwaysAutoResize) && !window_was_visible) + if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && !window_was_visible) { window->HiddenFrames = 1; - if (!window_size_set_by_api) - window->Size = window->SizeFull = ImVec2(0.f, 0.f); - window->SizeContents = ImVec2(0.f, 0.f); + if (flags & ImGuiWindowFlags_AlwaysAutoResize) + { + if (!window_size_set_by_api) + window->Size = window->SizeFull = ImVec2(0.f, 0.f); + window->SizeContents = ImVec2(0.f, 0.f); + } } // Calculate auto-fit size @@ -3742,10 +3745,20 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ rect_to_avoid = ImRect(parent_window->Pos.x + style.ItemSpacing.x, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - style.ItemSpacing.x - parent_window->ScrollbarWidth(), FLT_MAX); // We want some overlap to convey the relative depth of each popup (here hard-coded to 4) window->PosFloat = FindBestWindowPos(window->PosFloat, window->Size, flags, &window->AutoPosLastDirection, rect_to_avoid); } - else if ((flags & ImGuiWindowFlags_Popup) != 0 && window_appearing_after_being_hidden && !window_pos_set_by_api) + else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_appearing_after_being_hidden) { - ImRect rect_to_avoid(window->PosFloat.x - 1, window->PosFloat.y - 1, window->PosFloat.x + 1, window->PosFloat.y + 1); - window->PosFloat = FindBestWindowPos(window->PosFloat, window->Size, flags, &window->AutoPosLastDirection, rect_to_avoid); + if (flags & ImGuiWindowFlags_Modal) + { + // Center + // FIXME: Should be widely available, e.g. via SetNextWindowPos() API etc. + ImRect fullscreen_rect(GetVisibleRect()); + window->PosFloat = ImMax(style.DisplaySafeAreaPadding, fullscreen_rect.GetCenter() - window->SizeContents * 0.5f); + } + else + { + ImRect rect_to_avoid(window->PosFloat.x - 1, window->PosFloat.y - 1, window->PosFloat.x + 1, window->PosFloat.y + 1); + window->PosFloat = FindBestWindowPos(window->PosFloat, window->Size, flags, &window->AutoPosLastDirection, rect_to_avoid); + } } // Position tooltip (always follows mouse) @@ -3814,8 +3827,8 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ // Modal window darkens what is behind them if ((flags & ImGuiWindowFlags_Modal) != 0 && window == GetFrontMostModalRootWindow()) { - ImVec4 fullscreen_rect = GetVisibleRect(); - window->DrawList->AddRectFilled(ImVec2(fullscreen_rect.x, fullscreen_rect.y), ImVec2(fullscreen_rect.z, fullscreen_rect.w), window->Color(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); + ImRect fullscreen_rect = GetVisibleRect(); + window->DrawList->AddRectFilled(fullscreen_rect.Min, fullscreen_rect.Max, window->Color(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); } // Draw window + handle manual resize From bcbf53857c837324bdee5e5c619cc5a3c3508598 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 23 Jun 2015 15:17:27 -0600 Subject: [PATCH 10/25] BeginPopupModal() default to NoCollapse for modal windows (#249) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5b46fafc..67f01d5d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3257,7 +3257,7 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_opened, ImGuiWindowFlags e return false; } - ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoSavedSettings; + ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings; bool opened = ImGui::Begin(name, p_opened, ImVec2(0.0f, 0.0f), -1.0f, flags); if (!opened || (p_opened && !*p_opened)) // Opened can be 'false' when the popup is completely clipped (e.g. zero size display) { @@ -11519,7 +11519,7 @@ void ImGui::ShowTestWindow(bool* opened) if (ImGui::Button("Delete..")) ImGui::OpenPopup("Delete?"); - if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse)) + if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize)) { ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n"); ImGui::Separator(); From 54362669637b92675845561bd23ecc4bd77e6a9a Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 23 Jun 2015 15:34:44 -0600 Subject: [PATCH 11/25] Added SetNextWindowPosCenter() (#249) --- imgui.cpp | 37 +++++++++++++++++++++++-------------- imgui.h | 9 +++++---- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 67f01d5d..f058d156 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3562,12 +3562,16 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ // Process SetNextWindow***() calls bool window_pos_set_by_api = false, window_size_set_by_api = false; + bool window_pos_center = false; if (g.SetNextWindowPosCond) { const ImVec2 backup_cursor_pos = window->DC.CursorPos; // FIXME: not sure of the exact reason of this anymore :( need to look into that. if (!window_was_visible) window->SetWindowPosAllowFlags |= ImGuiSetCond_Appearing; window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) != 0; - ImGui::SetWindowPos(g.SetNextWindowPosVal, g.SetNextWindowPosCond); + if (window_pos_set_by_api && ImLengthSqr(g.SetNextWindowPosVal - ImVec2(-FLT_MAX,-FLT_MAX)) < 0.001f) + window_pos_center = true; + else + ImGui::SetWindowPos(g.SetNextWindowPosVal, g.SetNextWindowPosCond); window->DC.CursorPos = backup_cursor_pos; g.SetNextWindowPosCond = 0; } @@ -3735,7 +3739,15 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ } // Position popup - if (flags & ImGuiWindowFlags_ChildMenu) + if ((flags & ImGuiWindowFlags_Modal) && !window_pos_set_by_api && window_appearing_after_being_hidden) + window_pos_center = true; + + if (window_pos_center) + { + ImRect fullscreen_rect(GetVisibleRect()); + SetWindowPos(ImMax(style.DisplaySafeAreaPadding, fullscreen_rect.GetCenter() - window->SizeFull * 0.5f)); + } + else if (flags & ImGuiWindowFlags_ChildMenu) { IM_ASSERT(window_pos_set_by_api); ImRect rect_to_avoid; @@ -3747,18 +3759,8 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ } else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_appearing_after_being_hidden) { - if (flags & ImGuiWindowFlags_Modal) - { - // Center - // FIXME: Should be widely available, e.g. via SetNextWindowPos() API etc. - ImRect fullscreen_rect(GetVisibleRect()); - window->PosFloat = ImMax(style.DisplaySafeAreaPadding, fullscreen_rect.GetCenter() - window->SizeContents * 0.5f); - } - else - { - ImRect rect_to_avoid(window->PosFloat.x - 1, window->PosFloat.y - 1, window->PosFloat.x + 1, window->PosFloat.y + 1); - window->PosFloat = FindBestWindowPos(window->PosFloat, window->Size, flags, &window->AutoPosLastDirection, rect_to_avoid); - } + ImRect rect_to_avoid(window->PosFloat.x - 1, window->PosFloat.y - 1, window->PosFloat.x + 1, window->PosFloat.y + 1); + window->PosFloat = FindBestWindowPos(window->PosFloat, window->Size, flags, &window->AutoPosLastDirection, rect_to_avoid); } // Position tooltip (always follows mouse) @@ -4601,6 +4603,13 @@ void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiSetCond cond) g.SetNextWindowPosCond = cond ? cond : ImGuiSetCond_Always; } +void ImGui::SetNextWindowPosCenter(ImGuiSetCond cond) +{ + ImGuiState& g = *GImGui; + g.SetNextWindowPosVal = ImVec2(-FLT_MAX, -FLT_MAX); + g.SetNextWindowPosCond = cond ? cond : ImGuiSetCond_Always; +} + void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiSetCond cond) { ImGuiState& g = *GImGui; diff --git a/imgui.h b/imgui.h index b0b5914d..fac75487 100644 --- a/imgui.h +++ b/imgui.h @@ -122,10 +122,11 @@ namespace ImGui IMGUI_API float GetWindowWidth(); IMGUI_API bool IsWindowCollapsed(); - IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiSetCond cond = 0); // set next window position - call before Begin() - IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiSetCond cond = 0); // set next window size. set to ImVec2(0,0) to force an auto-fit - IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiSetCond cond = 0); // set next window collapsed state - IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most + IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiSetCond cond = 0); // set next window position. call before Begin() + IMGUI_API void SetNextWindowPosCenter(ImGuiSetCond cond = 0); // set next window position to be centered on screen. call before Begin() + IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiSetCond cond = 0); // set next window size. set to ImVec2(0,0) to force an auto-fit. call before Begin() + IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiSetCond cond = 0); // set next window collapsed state. call before Begin() + IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most. call before Begin() IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiSetCond cond = 0); // set current window position - call within Begin()/End(). may incur tearing IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiSetCond cond = 0); // set current window size. set to ImVec2(0,0) to force an auto-fit. may incur tearing IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiSetCond cond = 0); // set current window collapsed state From d171e48b203295d0a0bdbef8d3d6706b989d23a5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 23 Jun 2015 15:45:34 -0600 Subject: [PATCH 12/25] Fixed SetNextWindowPosCenter() being processed too early for windows that are still measuring their size (for #249) --- imgui.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f058d156..676202e6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1426,6 +1426,7 @@ struct ImGuiWindow int SetWindowPosAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowPos() call will succeed with this particular flag. int SetWindowSizeAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowSize() call will succeed with this particular flag. int SetWindowCollapsedAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowCollapsed() call will succeed with this particular flag. + bool SetWindowPosCenterWanted; ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack @@ -1787,6 +1788,7 @@ ImGuiWindow::ImGuiWindow(const char* name) AutoPosLastDirection = -1; HiddenFrames = 0; SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiSetCond_Always | ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing; + SetWindowPosCenterWanted = false; LastFrameDrawn = -1; ItemWidthDefault = 0.0f; @@ -3562,16 +3564,20 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ // Process SetNextWindow***() calls bool window_pos_set_by_api = false, window_size_set_by_api = false; - bool window_pos_center = false; if (g.SetNextWindowPosCond) { const ImVec2 backup_cursor_pos = window->DC.CursorPos; // FIXME: not sure of the exact reason of this anymore :( need to look into that. if (!window_was_visible) window->SetWindowPosAllowFlags |= ImGuiSetCond_Appearing; window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) != 0; if (window_pos_set_by_api && ImLengthSqr(g.SetNextWindowPosVal - ImVec2(-FLT_MAX,-FLT_MAX)) < 0.001f) - window_pos_center = true; + { + window->SetWindowPosCenterWanted = true; // May be processed on the next frame if this is our first frame and we are measuring size + window->SetWindowPosAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing); + } else + { ImGui::SetWindowPos(g.SetNextWindowPosVal, g.SetNextWindowPosCond); + } window->DC.CursorPos = backup_cursor_pos; g.SetNextWindowPosCond = 0; } @@ -3738,12 +3744,12 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ window->Size = window->SizeFull = size_on_first_use; // NB: argument name 'size_on_first_use' misleading here, it's really just 'size' as provided by user. } - // Position popup - if ((flags & ImGuiWindowFlags_Modal) && !window_pos_set_by_api && window_appearing_after_being_hidden) - window_pos_center = true; - + bool window_pos_center = false; + window_pos_center |= (window->SetWindowPosCenterWanted && window->HiddenFrames == 0); + window_pos_center |= ((flags & ImGuiWindowFlags_Modal) && !window_pos_set_by_api && window_appearing_after_being_hidden); if (window_pos_center) { + // Center (any sort of window) ImRect fullscreen_rect(GetVisibleRect()); SetWindowPos(ImMax(style.DisplaySafeAreaPadding, fullscreen_rect.GetCenter() - window->SizeFull * 0.5f)); } @@ -4485,6 +4491,7 @@ static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiSetCond co if (cond && (window->SetWindowPosAllowFlags & cond) == 0) return; window->SetWindowPosAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing); + window->SetWindowPosCenterWanted = false; // Set const ImVec2 old_pos = window->Pos; From 975ef00682009196f18ca6b2d9a13aba200efe21 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jun 2015 19:53:41 -0600 Subject: [PATCH 13/25] Minor construction fix (-1.0 is correct "disabled" value for TextWrapPos, didn't have any incidence anyway) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 676202e6..a1382ce7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1179,7 +1179,7 @@ struct ImGuiDrawContext ItemWidth = 0.0f; ButtonRepeat = false; AllowKeyboardFocus = true; - TextWrapPos = 1.0f; + TextWrapPos = -1.0f; ColorEditMode = ImGuiColorEditMode_RGB; memset(StackSizesBackup, 0, sizeof(StackSizesBackup)); From af5890b27695a8d175ae0b2f9468d18a639c043c Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jun 2015 20:08:08 -0600 Subject: [PATCH 14/25] AutoFit can be triggered on each axis separately via SetNextWindowSize() (mentioned in #249) --- imgui.cpp | 61 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a1382ce7..660ceaa3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1419,7 +1419,7 @@ struct ImGuiWindow bool SkipItems; // == Visible && !Collapsed int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) ImGuiID PopupID; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) - int AutoFitFrames; + int AutoFitFramesX, AutoFitFramesY; bool AutoFitOnlyGrows; int AutoPosLastDirection; int HiddenFrames; @@ -1783,7 +1783,7 @@ ImGuiWindow::ImGuiWindow(const char* name) SkipItems = false; BeginCount = 0; PopupID = 0; - AutoFitFrames = -1; + AutoFitFramesX = AutoFitFramesY = -1; AutoFitOnlyGrows = false; AutoPosLastDirection = -1; HiddenFrames = 0; @@ -3499,13 +3499,16 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl if ((flags & ImGuiWindowFlags_AlwaysAutoResize) != 0) { - window->AutoFitFrames = 2; + window->AutoFitFramesX = window->AutoFitFramesY = 2; window->AutoFitOnlyGrows = false; } - else if (ImLengthSqr(window->Size) < 0.00001f) + else { - window->AutoFitFrames = 2; - window->AutoFitOnlyGrows = true; + if (window->Size.x <= 0.0f) + window->AutoFitFramesX = 2; + if (window->Size.y <= 0.0f) + window->AutoFitFramesY = 2; + window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0); } g.Windows.push_back(window); @@ -3705,8 +3708,10 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ { // We still process initial auto-fit on collapsed windows to get a window width, // But otherwise we don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed. - if (window->AutoFitFrames > 0) - window->SizeFull = window->AutoFitOnlyGrows ? ImMax(window->SizeFull, size_auto_fit) : size_auto_fit; + if (window->AutoFitFramesX > 0) + window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x; + if (window->AutoFitFramesY > 0) + window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y; window->Size = window->TitleBarRect().GetSize(); } else @@ -3715,10 +3720,13 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ { window->SizeFull = size_auto_fit; } - else if (window->AutoFitFrames > 0 && !window_size_set_by_api) + else if ((window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) && !window_size_set_by_api) { // Auto-fit only grows during the first few frames - window->SizeFull = window->AutoFitOnlyGrows ? ImMax(window->SizeFull, size_auto_fit) : size_auto_fit; + if (window->AutoFitFramesX > 0) + window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x; + if (window->AutoFitFramesY > 0) + window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y; if (!(flags & ImGuiWindowFlags_NoSavedSettings)) MarkSettingsDirty(); } @@ -3801,7 +3809,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ // Clamp position so it stays visible if (!(flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip)) { - if (!window_pos_set_by_api && window->AutoFitFrames <= 0 && g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing. + if (!window_pos_set_by_api && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing. { ImVec2 padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding); window->PosFloat = ImMax(window->PosFloat + window->Size, padding) - window->Size; @@ -3855,7 +3863,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ else { ImU32 resize_col = 0; - if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFrames <= 0 && !(flags & ImGuiWindowFlags_NoResize)) + if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && !(flags & ImGuiWindowFlags_NoResize)) { // Manual resize const ImRect resize_rect(window->Rect().GetBR()-ImVec2(14,14), window->Rect().GetBR()); @@ -3980,8 +3988,10 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ window->DC.GroupStack.resize(0); window->MenuColumns.Update(3, style.ItemSpacing.x, !window_was_visible); - if (window->AutoFitFrames > 0) - window->AutoFitFrames--; + if (window->AutoFitFramesX > 0) + window->AutoFitFramesX--; + if (window->AutoFitFramesY > 0) + window->AutoFitFramesY--; // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) @@ -4039,7 +4049,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ IM_ASSERT((flags & ImGuiWindowFlags_NoTitleBar) != 0); window->Collapsed = parent_window && parent_window->Collapsed; - if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFrames <= 0) + if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) { const ImVec4 clip_rect_t = window->ClipRectStack.back(); window->Collapsed |= (clip_rect_t.x >= clip_rect_t.z || clip_rect_t.y >= clip_rect_t.w); @@ -4054,7 +4064,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ window->Active = false; // Return false if we don't intend to display anything to allow user to perform an early out optimization - window->SkipItems = (window->Collapsed || !window->Active) && window->AutoFitFrames <= 0; + window->SkipItems = (window->Collapsed || !window->Active) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0; return !window->SkipItems; } @@ -4528,15 +4538,24 @@ static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiSetCond window->SetWindowSizeAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing); // Set - if (ImLengthSqr(size) > 0.00001f) + if (size.x > 0.0f) { - window->SizeFull = size; - window->AutoFitFrames = 0; + window->AutoFitFramesX = 0; + window->SizeFull.x = size.x; } else { - // Autofit - window->AutoFitFrames = 2; + window->AutoFitFramesX = 2; + window->AutoFitOnlyGrows = false; + } + if (size.y > 0.0f) + { + window->AutoFitFramesY = 0; + window->SizeFull.y = size.y; + } + else + { + window->AutoFitFramesY = 2; window->AutoFitOnlyGrows = false; } } From 4976bf97a6bb5a5cc934748724daf32c0e8a40c8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jun 2015 20:35:40 -0600 Subject: [PATCH 15/25] Fix for correctness and allow non-auto resized modals to have window minimum size applied - hopefully no-side effects (#249) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 660ceaa3..d8221d55 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3734,7 +3734,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ } // Minimum window size - if (!(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip))) + if (!(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysAutoResize))) { window->SizeFull = ImMax(window->SizeFull, style.WindowMinSize); if (!window->Collapsed) From 8224ca16b640ec9847ccdf598489bf14794312ab Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jun 2015 20:45:06 -0600 Subject: [PATCH 16/25] Carriage return in demo tooltip --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index d8221d55..e6bfc925 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11100,7 +11100,7 @@ void ImGui::ShowTestWindow(bool* opened) static float col1[3] = { 1.0f,0.0f,0.2f }; static float col2[4] = { 0.4f,0.7f,0.0f,0.5f }; ImGui::ColorEdit3("color 1", col1); - ImGui::SameLine(); ShowHelpMarker("Click on the colored square to change edit mode. CTRL+click on individual component to input value.\n"); + ImGui::SameLine(); ShowHelpMarker("Click on the colored square to change edit mode.\nCTRL+click on individual component to input value.\n"); ImGui::ColorEdit4("color 2", col2); From ea2c824192b48b5138ed9961e37f1357a63e57ce Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 25 Jun 2015 21:38:24 -0600 Subject: [PATCH 17/25] Version 1.41 --- imgui.cpp | 2 +- imgui.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e6bfc925..5ddb01bd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// ImGui library v1.41 WIP +// ImGui library v1.41 // See ImGui::ShowTestWindow() for sample code. // Read 'Programmer guide' below for notes on how to setup ImGui in your codebase. // Get latest version at https://github.com/ocornut/imgui diff --git a/imgui.h b/imgui.h index fac75487..da9153f0 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// ImGui library v1.41 WIP +// ImGui library v1.41 // See .cpp file for documentation. // See ImGui::ShowTestWindow() for sample code. // Read 'Programmer guide' in .cpp for notes on how to setup ImGui in your codebase. @@ -13,7 +13,7 @@ #include // NULL, malloc, free, qsort, atoi #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp -#define IMGUI_VERSION "1.41 WIP" +#define IMGUI_VERSION "1.41" // Define assertion handler. #ifndef IM_ASSERT From f66be0e7b2cde427ba34772b9f30d27fd4c00df9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 25 Jun 2015 21:52:16 -0600 Subject: [PATCH 18/25] Demo: satisfying buffer size --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 5ddb01bd..c731909f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10975,7 +10975,7 @@ void ImGui::ShowTestWindow(bool* opened) if (ImGui::TreeNode("Multi-line Text Input")) { - static char text[1024*4] = "// F00F bug\nlabel:\n\tlock cmpxchg8b eax\n"; + static char text[1024*16] = "// F00F bug\nlabel:\n\tlock cmpxchg8b eax\n"; ImGui::PushItemWidth(-1.0f); ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(0.f, ImGui::GetTextLineHeight() * 16), ImGuiInputTextFlags_AllowTabInput); ImGui::PopItemWidth(); From 5cd1a0151461f88401e525e7c0ab9a68f3cb82a6 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Fri, 26 Jun 2015 18:49:45 -0700 Subject: [PATCH 19/25] Fixing 64-bit compilation warning caused by implicit size_t->int cast --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index c731909f..f2c88e4c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3192,7 +3192,7 @@ static void ClosePopup(ImGuiID id) if (!IsPopupOpen(id)) return; ImGuiState& g = *GImGui; - ClosePopupToLevel(g.OpenedPopupStack.size() - 1); + ClosePopupToLevel((int)g.OpenedPopupStack.size() - 1); } // Close the popup we have begin-ed into. From 4ac21aaa12f75c4c5ee86d58cbbb572841a73f17 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 26 Jun 2015 20:48:53 -0600 Subject: [PATCH 20/25] Version number 1.42 wip + todo list entries --- imgui.cpp | 29 ++++++++++++++++------------- imgui.h | 4 ++-- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f2c88e4c..f0577b05 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// ImGui library v1.41 +// ImGui library v1.42 wip // See ImGui::ShowTestWindow() for sample code. // Read 'Programmer guide' below for notes on how to setup ImGui in your codebase. // Get latest version at https://github.com/ocornut/imgui @@ -327,6 +327,7 @@ ISSUES & TODO-LIST ================== + Issue numbers (#) refer to github issues. - misc: merge or clarify ImVec4 vs ImRect? - window: fix resize grip rendering scaling along with Rounding style setting @@ -335,6 +336,7 @@ - window: allow resizing of child windows (possibly given min/max for each axis?) - window: background options for child windows, border option (disable rounding) - window: resizing from any sides? + mouse cursor directives for app. + - window: get size/pos helpers given names (see discussion in #249) - scrolling: add horizontal scroll !- scrolling: set scrolling given a position. !- scrolling: allow immediately effective change of scroll if we haven't appended items yet @@ -343,31 +345,32 @@ - main: considering adding EndFrame()/Init(). some constructs are awkward in the implementation because of the lack of them. - main: IsItemHovered() make it more consistent for various type of widgets, widgets with multiple components, etc. also effectively IsHovered() region sometimes differs from hot region, e.g tree nodes - main: IsItemHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of the TreeNode? - - input text: add ImGuiInputTextFlags_EnterToApply? (off github issue #218) -!- input text: multiple lines inputs (#200) + - input text: add ImGuiInputTextFlags_EnterToApply? (off #218) + - input text multi-line: way to dynamically grow the buffer without forcing the user to initially allocate for worse case (follow up on #200) + - input text multi-line: line numbers? status bar? (follow up on #200) !- input number: large int not reliably supported because of int<>float conversions. - input number: optional range min/max for Input*() functions - input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled) - input number: use mouse wheel to step up/down - input number: non-decimal input. - text: proper alignment options - - layout: horizontal layout helper (github issue #97) + - layout: horizontal layout helper (#97) - layout: more generic alignment state (left/right/centered) for single items? - layout: clean up the InputFloatN/SliderFloatN/ColorEdit4 layout code. item width should include frame padding. - - columns: separator function or parameter that works within the column (currently Separator() bypass all columns) (github issue #125) - - columns: declare column set (each column: fixed size, %, fill, distribute default size among fills) (github issue #125) - - columns: columns header to act as button (~sort op) and allow resize/reorder (github issue #125) - - columns: user specify columns size (github issue #125) - - popup: border options. richer api like BeginChild() perhaps? (github issue #197) + - columns: separator function or parameter that works within the column (currently Separator() bypass all columns) (#125) + - columns: declare column set (each column: fixed size, %, fill, distribute default size among fills) (#125) + - columns: columns header to act as button (~sort op) and allow resize/reorder (#125) + - columns: user specify columns size (#125) + - popup: border options. richer api like BeginChild() perhaps? (#197) - combo: sparse combo boxes (via function call?) - combo: turn child handling code into pop up helper - combo: contents should extends to fit label if combo widget is small - - combo/listbox: keyboard control. need inputtext like non-active focus + key handling. considering keybord for custom listbox (see github pr #203) + - combo/listbox: keyboard control. need inputtext like non-active focus + key handling. considering keybord for custom listbox (pr #203) - listbox: multiple selection - listbox: user may want to initial scroll to focus on the one selected value? - listbox: keyboard navigation. - listbox: scrolling should track modified selection. - - menus: local shortcuts, global shortcuts (github issue #126) + - menus: local shortcuts, global shortcuts (#126) - menus: icons - menus: see we can allow for click-menu-hold-release-on-item to work (like Windows does) - menus: menubars: some sort of priority / effect of main menu-bar on desktop size? @@ -389,7 +392,7 @@ - text edit: field resize behavior - field could stretch when being edited? hover tooltip shows more text? - text edit: add multi-line text edit - tree: add treenode/treepush int variants? because (void*) cast from int warns on some platforms/settings - - tooltip: figure out a way to use TextWrapped() in a tooltip. + - textwrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (git issue #249) - settings: write more decent code to allow saving/loading new fields - settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file - style: store rounded corners in texture to use 1 quad per corner (filled and wireframe). so rounding have minor cost. @@ -407,7 +410,7 @@ - keyboard: full keyboard navigation and focus. - input: rework IO to be able to pass actual events to fix temporal aliasing issues. - input: support track pad style scrolling & slider edit. - - portability: big-endian test/support (github issue #81) + - portability: big-endian test/support (#81) - memory: add a way to discard allocs of unused/transient windows. with the current architecture new windows (including popup, opened combos, listbox) perform at least 3 allocs. - misc: mark printf compiler attributes on relevant functions - misc: provide a way to compile out the entire implementation while providing a dummy API (e.g. #define IMGUI_DUMMY_IMPL) diff --git a/imgui.h b/imgui.h index da9153f0..51dcca92 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// ImGui library v1.41 +// ImGui library v1.42 // See .cpp file for documentation. // See ImGui::ShowTestWindow() for sample code. // Read 'Programmer guide' in .cpp for notes on how to setup ImGui in your codebase. @@ -13,7 +13,7 @@ #include // NULL, malloc, free, qsort, atoi #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp -#define IMGUI_VERSION "1.41" +#define IMGUI_VERSION "1.42 wip" // Define assertion handler. #ifndef IM_ASSERT From 0783697f87b9f948bab4b8438f30f0220b155f1b Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 29 Jun 2015 10:39:17 -0600 Subject: [PATCH 21/25] Minor tidying up --- imgui.cpp | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f0577b05..2d33d0af 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -430,7 +430,7 @@ #include "imgui.h" #include // toupper, isprint #include // sqrtf, fabsf, fmodf, powf, cosf, sinf, floorf, ceilf -#include // vsnprintf, sscanf +#include // vsnprintf, sscanf, printf #include // new (ptr) #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier #include // intptr_t @@ -711,8 +711,7 @@ void ImGuiIO::AddInputCharacter(ImWchar c) #define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) -#undef PI -const float PI = 3.14159265358979323846f; +const float IM_PI = 3.14159265358979323846f; #ifdef INT_MAX #define IM_INT_MIN INT_MIN @@ -724,9 +723,9 @@ const float PI = 3.14159265358979323846f; // Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n. #ifdef _MSC_VER -#define STR_NEWLINE "\r\n" +#define IM_NEWLINE "\r\n" #else -#define STR_NEWLINE "\n" +#define IM_NEWLINE "\n" #endif // Math bits @@ -2573,7 +2572,7 @@ static void LogText(const ImVec2& ref_pos, const char* text, const char* text_en { const int char_count = (int)(line_end - text_remaining); if (log_new_line || !is_first_line) - ImGui::LogText(STR_NEWLINE "%*s%.*s", tree_depth*4, "", char_count, text_remaining); + ImGui::LogText(IM_NEWLINE "%*s%.*s", tree_depth*4, "", char_count, text_remaining); else ImGui::LogText(" %.*s", char_count, text_remaining); } @@ -5349,7 +5348,7 @@ void ImGui::LogFinish() if (!g.LogEnabled) return; - ImGui::LogText(STR_NEWLINE); + ImGui::LogText(IM_NEWLINE); g.LogEnabled = false; if (g.LogFile != NULL) { @@ -6052,9 +6051,9 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, float v_degrees_max) { - float v_deg = (*v_rad) * 360.0f / (2*PI); + float v_deg = (*v_rad) * 360.0f / (2*IM_PI); bool value_changed = ImGui::SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, "%.0f deg", 1.0f); - *v_rad = v_deg * (2*PI) / 360.0f; + *v_rad = v_deg * (2*IM_PI) / 360.0f; return value_changed; } @@ -8319,7 +8318,7 @@ void ImGui::Separator() ImGuiState& g = *GImGui; if (g.LogEnabled) - ImGui::LogText(STR_NEWLINE "--------------------------------"); + ImGui::LogText(IM_NEWLINE "--------------------------------"); if (window->DC.ColumnsCount > 1) { @@ -9025,9 +9024,9 @@ void ImDrawList::AddArcFast(const ImVec2& center, float radius, ImU32 col, int a { for (int i = 0; i < SAMPLES; i++) { - const float a = ((float)i / (float)SAMPLES) * 2*PI; - circle_vtx[i].x = cosf(a + PI); - circle_vtx[i].y = sinf(a + PI); + const float a = ((float)i / (float)SAMPLES) * 2*IM_PI; + circle_vtx[i].x = cosf(a + IM_PI); + circle_vtx[i].y = sinf(a + IM_PI); } circle_vtx_builds = true; } @@ -9137,7 +9136,7 @@ void ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int nu return; PrimReserve((unsigned int)num_segments*6); - const float a_step = 2*PI/(float)num_segments; + const float a_step = 2*IM_PI/(float)num_segments; float a0 = 0.0f; for (int i = 0; i < num_segments; i++) { @@ -9154,7 +9153,7 @@ void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, const ImVec2 uv = GImGui->FontTexUvWhitePixel; PrimReserve((unsigned int)num_segments*3); - const float a_step = 2*PI/(float)num_segments; + const float a_step = 2*IM_PI/(float)num_segments; float a0 = 0.0f; for (int i = 0; i < num_segments; i++) { @@ -10582,13 +10581,13 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::LogToClipboard(); else ImGui::LogToTTY(); - ImGui::LogText("ImGuiStyle& style = ImGui::GetStyle();" STR_NEWLINE); + ImGui::LogText("ImGuiStyle& style = ImGui::GetStyle();" IM_NEWLINE); for (int i = 0; i < ImGuiCol_COUNT; i++) { const ImVec4& col = style.Colors[i]; const char* name = ImGui::GetStyleColName(i); if (!output_only_modified || memcmp(&col, (ref ? &ref->Colors[i] : &def.Colors[i]), sizeof(ImVec4)) != 0) - ImGui::LogText("style.Colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" STR_NEWLINE, name, 22 - strlen(name), "", col.x, col.y, col.z, col.w); + ImGui::LogText("style.Colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE, name, 22 - strlen(name), "", col.x, col.y, col.z, col.w); } ImGui::LogFinish(); } @@ -11532,7 +11531,7 @@ void ImGui::ShowTestWindow(bool* opened) if (ImGui::BeginPopupContextItem("item context menu")) { if (ImGui::Selectable("Set to zero")) value = 0.0f; - if (ImGui::Selectable("Set to PI")) value = PI; + if (ImGui::Selectable("Set to PI")) value = 3.1415f; ImGui::EndPopup(); } @@ -12196,9 +12195,9 @@ struct ExampleAppConsole const char* item = Items[i]; if (!filter.PassFilter(item)) continue; - ImVec4 col(1,1,1,1); // A better implement may store a type per-item. For the sample let's just parse the text. - if (strstr(item, "[error]")) col = ImVec4(1.0f,0.4f,0.4f,1.0f); - else if (strncmp(item, "# ", 2) == 0) col = ImVec4(1.0f,0.8f,0.6f,1.0f); + ImVec4 col = ImColor(255,255,255); // A better implementation may store a type per-item. For the sample let's just parse the text. + if (strstr(item, "[error]")) col = ImColor(255,100,100); + else if (strncmp(item, "# ", 2) == 0) col = ImColor(255,200,150); ImGui::PushStyleColor(ImGuiCol_Text, col); ImGui::TextUnformatted(item); ImGui::PopStyleColor(); From 8b392feba17af2af7b9015af4f1296f07429f574 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 29 Jun 2015 12:36:24 -0600 Subject: [PATCH 22/25] Tidying up - moved ImFontAtlas glyph ranges helpers outside of ImFont block --- imgui.cpp | 68 +++++++++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2d33d0af..44b44b36 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9669,40 +9669,6 @@ void ImFontAtlas::RenderCustomTexData(int pass, void* p_rects) } } -//----------------------------------------------------------------------------- -// ImFont -//----------------------------------------------------------------------------- - -ImFont::ImFont() -{ - Scale = 1.0f; - FallbackChar = (ImWchar)'?'; - Clear(); -} - -ImFont::~ImFont() -{ - // Invalidate active font so that the user gets a clear crash instead of a dangling pointer. - // If you want to delete fonts you need to do it between Render() and NewFrame(). - ImGuiState& g = *GImGui; - if (g.Font == this) - g.Font = NULL; - Clear(); -} - -void ImFont::Clear() -{ - FontSize = 0.0f; - DisplayOffset = ImVec2(-0.5f, 0.5f); - Ascent = Descent = 0.0f; - ContainerAtlas = NULL; - Glyphs.clear(); - FallbackGlyph = NULL; - FallbackXAdvance = 0.0f; - IndexXAdvance.clear(); - IndexLookup.clear(); -} - // Retrieve list of range (2 int per range, values are inclusive) const ImWchar* ImFontAtlas::GetGlyphRangesDefault() { @@ -9801,6 +9767,40 @@ const ImWchar* ImFontAtlas::GetGlyphRangesCyrillic() return &ranges[0]; } +//----------------------------------------------------------------------------- +// ImFont +//----------------------------------------------------------------------------- + +ImFont::ImFont() +{ + Scale = 1.0f; + FallbackChar = (ImWchar)'?'; + Clear(); +} + +ImFont::~ImFont() +{ + // Invalidate active font so that the user gets a clear crash instead of a dangling pointer. + // If you want to delete fonts you need to do it between Render() and NewFrame(). + ImGuiState& g = *GImGui; + if (g.Font == this) + g.Font = NULL; + Clear(); +} + +void ImFont::Clear() +{ + FontSize = 0.0f; + DisplayOffset = ImVec2(-0.5f, 0.5f); + Ascent = Descent = 0.0f; + ContainerAtlas = NULL; + Glyphs.clear(); + FallbackGlyph = NULL; + FallbackXAdvance = 0.0f; + IndexXAdvance.clear(); + IndexLookup.clear(); +} + void ImFont::BuildLookupTable() { int max_codepoint = 0; From 039ebb79f4418a9a2375cec9406302930aeab046 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 29 Jun 2015 13:18:44 -0600 Subject: [PATCH 23/25] Tidying up - renamed a few internal functions --- imgui.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 44b44b36..a607fc55 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5768,7 +5768,7 @@ static bool SliderFloatAsInputText(const char* label, float* v, ImGuiID id, int } // Parse display precision back from the display format string -static inline void ParseFormat(const char* fmt, int& decimal_precision) +static inline void ParseFormatPrecision(const char* fmt, int& decimal_precision) { while ((fmt = strchr(fmt, '%')) != NULL) { @@ -5803,7 +5803,7 @@ static inline float RoundScalar(float value, int decimal_precision) return negative ? -value : value; } -static bool SliderScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, bool horizontal) +static bool SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, bool horizontal) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -5965,7 +5965,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c if (!display_format) display_format = "%.3f"; int decimal_precision = 3; - ParseFormat(display_format, decimal_precision); + ParseFormatPrecision(display_format, decimal_precision); // Tabbing or CTRL-clicking on Slider turns it into an input box bool start_text_input = false; @@ -5988,7 +5988,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c ItemSize(total_bb, style.FramePadding.y); // Actual slider behavior + render grab - const bool value_changed = SliderScalarBehavior(frame_bb, id, v, v_min, v_max, power, decimal_precision, true); + const bool value_changed = SliderBehavior(frame_bb, id, v, v_min, v_max, power, decimal_precision, true); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. char value_buf[64]; @@ -6026,7 +6026,7 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float if (!display_format) display_format = "%.3f"; int decimal_precision = 3; - ParseFormat(display_format, decimal_precision); + ParseFormatPrecision(display_format, decimal_precision); if (hovered && g.IO.MouseClicked[0]) { @@ -6035,7 +6035,7 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float } // Actual slider behavior + render grab - bool value_changed = SliderScalarBehavior(frame_bb, id, v, v_min, v_max, power, decimal_precision, false); + bool value_changed = SliderBehavior(frame_bb, id, v, v_min, v_max, power, decimal_precision, false); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. // For the vertical slider we allow centered text to overlap the frame padding @@ -6163,7 +6163,7 @@ bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const } // FIXME-WIP: Work in progress. May change API / behavior. -static bool DragScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power) +static bool DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -6269,7 +6269,7 @@ bool ImGui::DragFloat(const char* label, float *v, float v_speed, float v_min, f if (!display_format) display_format = "%.3f"; int decimal_precision = 3; - ParseFormat(display_format, decimal_precision); + ParseFormatPrecision(display_format, decimal_precision); // Tabbing or CTRL-clicking on Drag turns it into an input box bool start_text_input = false; @@ -6291,7 +6291,7 @@ bool ImGui::DragFloat(const char* label, float *v, float v_speed, float v_min, f ItemSize(total_bb, style.FramePadding.y); // Actual drag behavior - const bool value_changed = DragScalarBehavior(frame_bb, id, v, v_speed, v_min, v_max, decimal_precision, power); + const bool value_changed = DragBehavior(frame_bb, id, v, v_speed, v_min, v_max, decimal_precision, power); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. char value_buf[64]; From 882c7a8cefd5753f3ac28e98e2b28ac7cd9e9a08 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 29 Jun 2015 13:20:28 -0600 Subject: [PATCH 24/25] Tidying up - ShowUserGuide, ShowStyleEditor only uses public calls --- imgui.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a607fc55..d7edcd62 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10513,13 +10513,11 @@ void ImGui::ShowMetricsWindow(bool*) {} void ImGui::ShowUserGuide() { - ImGuiState& g = *GImGui; - ImGui::BulletText("Double-click on title bar to collapse window."); ImGui::BulletText("Click and drag on lower right corner to resize window."); ImGui::BulletText("Click and drag on any empty space to move window."); ImGui::BulletText("Mouse Wheel to scroll."); - if (g.IO.FontAllowUserScaling) + if (ImGui::GetIO().FontAllowUserScaling) ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents."); ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields."); ImGui::BulletText("CTRL+Click on a slider or drag box to input text."); @@ -10537,18 +10535,16 @@ void ImGui::ShowUserGuide() void ImGui::ShowStyleEditor(ImGuiStyle* ref) { - ImGuiState& g = *GImGui; - ImGuiStyle& style = g.Style; + ImGuiStyle& style = ImGui::GetStyle(); const ImGuiStyle def; // Default style - if (ImGui::Button("Revert Style")) - g.Style = ref ? *ref : def; + style = ref ? *ref : def; if (ref) { ImGui::SameLine(); if (ImGui::Button("Save Style")) - *ref = g.Style; + *ref = style; } ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.55f); @@ -12482,7 +12478,7 @@ static void ShowExampleAppLongText(bool* opened) //----------------------------------------------------------------------------- // Compressed with stb_compress() then converted to a C array. // Use the program in extra_fonts/binary_to_compressed_c.cpp to create the array from a TTF file. -// Decompressor from stb.h (public domain) by Sean Barrett https://github.com/nothings/stb/blob/master/stb.h +// Decompression from stb.h (public domain) by Sean Barrett https://github.com/nothings/stb/blob/master/stb.h //----------------------------------------------------------------------------- static unsigned int stb_decompress_length(unsigned char *input) From af0de5f357985e1e40b7afff2439065b2620e495 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 29 Jun 2015 13:30:37 -0600 Subject: [PATCH 25/25] Tidying up - ImRect doesn't use ImVec2 operators (so we can expose it later) --- imgui.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d7edcd62..125ccd8f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1035,10 +1035,10 @@ struct ImRect // 2D axis aligned bounding-box ImRect(const ImVec4& v) { Min.x = v.x; Min.y = v.y; Max.x = v.z; Max.y = v.w; } ImRect(float x1, float y1, float x2, float y2) { Min.x = x1; Min.y = y1; Max.x = x2; Max.y = y2; } - ImVec2 GetCenter() const { return Min + (Max-Min)*0.5f; } - ImVec2 GetSize() const { return Max-Min; } - float GetWidth() const { return (Max-Min).x; } - float GetHeight() const { return (Max-Min).y; } + ImVec2 GetCenter() const { return ImVec2((Min.x+Max.x)*0.5f, (Min.y+Max.y)*0.5f); } + ImVec2 GetSize() const { return ImVec2(Max.x-Min.x,Max.y-Min.y); } + float GetWidth() const { return Max.x-Min.x; } + float GetHeight() const { return Max.y-Min.y; } ImVec2 GetTL() const { return Min; } ImVec2 GetTR() const { return ImVec2(Max.x,Min.y); } ImVec2 GetBL() const { return ImVec2(Min.x,Max.y); } @@ -1049,8 +1049,8 @@ struct ImRect // 2D axis aligned bounding-box void Add(const ImVec2& rhs) { Min.x = ImMin(Min.x, rhs.x); Min.y = ImMin(Min.y, rhs.y); Max.x = ImMax(Max.x, rhs.x); Max.y = ImMax(Max.x, rhs.x); } void Add(const ImRect& rhs) { Min.x = ImMin(Min.x, rhs.Min.x); Min.y = ImMin(Min.y, rhs.Min.y); Max.x = ImMax(Max.x, rhs.Max.x); Max.y = ImMax(Max.y, rhs.Max.y); } void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; } - void Expand(const ImVec2& amount) { Min -= amount; Max += amount; } - void Reduce(const ImVec2& amount) { Min += amount; Max -= amount; } + void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; } + void Reduce(const ImVec2& amount) { Min.x += amount.x; Min.y += amount.y; Max.x -= amount.x; Max.y -= amount.y; } void Clip(const ImRect& clip) { Min.x = ImMax(Min.x, clip.Min.x); Min.y = ImMax(Min.y, clip.Min.y); Max.x = ImMin(Max.x, clip.Max.x); Max.y = ImMin(Max.y, clip.Max.y); } ImVec2 GetClosestPoint(ImVec2 p, bool on_edge) const { @@ -1063,7 +1063,6 @@ struct ImRect // 2D axis aligned bounding-box return p; } }; -typedef ImRect ImGuiAabb; // FIXME-OBSOLETE struct ImGuiGroupData {