diff --git a/imgui.cpp b/imgui.cpp index 83847900c..24d63ed87 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1475,8 +1475,8 @@ ImGuiWindow::ImGuiWindow(const char* name) SizeContents = SizeContentsExplicit = ImVec2(0.0f, 0.0f); WindowPadding = ImVec2(0.0f, 0.0f); Scroll = ImVec2(0.0f, 0.0f); - ScrollTargetRelY = FLT_MAX; - ScrollTargetCenterRatioY = 0.5f; + ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); + ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f); ScrollbarX = ScrollbarY = false; ScrollbarSizes = ImVec2(0.0f, 0.0f); Active = WasActive = false; @@ -3730,11 +3730,16 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = IM_INT_MAX; // Apply scrolling - if (window->ScrollTargetRelY < FLT_MAX) + if (window->ScrollTarget.x < FLT_MAX) { - float center_ratio_y = window->ScrollTargetCenterRatioY; - window->Scroll.y = window->ScrollTargetRelY - ((1.0f - center_ratio_y) * window->TitleBarHeight()) - (center_ratio_y * window->SizeFull.y); - window->ScrollTargetRelY = FLT_MAX; + window->Scroll.x = window->ScrollTarget.x; + window->ScrollTarget.x = FLT_MAX; + } + if (window->ScrollTarget.y < FLT_MAX) + { + float center_ratio = window->ScrollTargetCenterRatio.y; + window->Scroll.y = window->ScrollTarget.y - ((1.0f - center_ratio) * window->TitleBarHeight()) - (center_ratio * window->SizeFull.y); + window->ScrollTarget.y = FLT_MAX; } window->Scroll = ImMax(window->Scroll, ImVec2(0.0f, 0.0f)); if (!window->Collapsed && !window->SkipItems) @@ -4738,23 +4743,40 @@ void ImGui::SetCursorScreenPos(const ImVec2& screen_pos) window->DC.CursorPos = screen_pos; } +float ImGui::GetScrollX() +{ + return GImGui->CurrentWindow->Scroll.x; +} + float ImGui::GetScrollY() +{ + return GImGui->CurrentWindow->Scroll.y; +} + +float ImGui::GetScrollMaxX() { ImGuiWindow* window = GetCurrentWindowRead(); - return window->Scroll.y; + return window->SizeContents.x - window->SizeFull.x - window->ScrollbarSizes.x; } float ImGui::GetScrollMaxY() { ImGuiWindow* window = GetCurrentWindowRead(); - return window->SizeContents.y - window->SizeFull.y; + return window->SizeContents.y - window->SizeFull.y - window->ScrollbarSizes.y; +} + +void ImGui::SetScrollX(float scroll_x) +{ + ImGuiWindow* window = GetCurrentWindow(); + window->ScrollTarget.x = scroll_x; + window->ScrollTargetCenterRatio.x = 0.0f; } void ImGui::SetScrollY(float scroll_y) { ImGuiWindow* window = GetCurrentWindow(); - window->ScrollTargetRelY = scroll_y + window->TitleBarHeight(); // title bar height cancelled out when using ScrollTargetRelY - window->ScrollTargetCenterRatioY = 0.0f; + window->ScrollTarget.y = scroll_y + window->TitleBarHeight(); // title bar height canceled out when using ScrollTargetRelY + window->ScrollTargetCenterRatio.y = 0.0f; } void ImGui::SetScrollFromPosY(float pos_y, float center_y_ratio) @@ -4762,10 +4784,10 @@ void ImGui::SetScrollFromPosY(float pos_y, float center_y_ratio) // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); - window->ScrollTargetRelY = (float)(int)(pos_y + window->Scroll.y); - if (center_y_ratio <= 0.0f && window->ScrollTargetRelY <= window->WindowPadding.y) // Minor hack to make "scroll to top" take account of WindowPadding, else it would scroll to (WindowPadding.y - ItemSpacing.y) - window->ScrollTargetRelY = 0.0f; - window->ScrollTargetCenterRatioY = center_y_ratio; + window->ScrollTarget.y = (float)(int)(pos_y + window->Scroll.y); + if (center_y_ratio <= 0.0f && window->ScrollTarget.y <= window->WindowPadding.y) // Minor hack to make "scroll to top" take account of WindowPadding, else it would scroll to (WindowPadding.y - ItemSpacing.y) + window->ScrollTarget.y = 0.0f; + window->ScrollTargetCenterRatio.y = center_y_ratio; } // center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item. diff --git a/imgui.h b/imgui.h index d1aad6d4d..d012736b1 100644 --- a/imgui.h +++ b/imgui.h @@ -152,8 +152,11 @@ namespace ImGui IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiSetCond cond = 0); // set named window collapsed state IMGUI_API void SetWindowFocus(const char* name); // set named window to be focused / front-most. use NULL to remove focus. + IMGUI_API float GetScrollX(); // get scrolling amount [0..GetScrollMaxX()] IMGUI_API float GetScrollY(); // get scrolling amount [0..GetScrollMaxY()] - IMGUI_API float GetScrollMaxY(); // get maximum scrolling amount == ContentSize.Y - WindowSize.Y + IMGUI_API float GetScrollMaxX(); // get maximum scrolling amount ~~ ContentSize.X - WindowSize.X + IMGUI_API float GetScrollMaxY(); // get maximum scrolling amount ~~ ContentSize.Y - WindowSize.Y + IMGUI_API void SetScrollX(float scroll_x); // set scrolling amount [0..GetScrollMaxX()] IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0..GetScrollMaxY()] IMGUI_API void SetScrollHere(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. IMGUI_API void SetScrollFromPosY(float pos_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position valid. use GetCursorPos() or GetCursorStartPos()+offset to get valid positions. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 1ebb408e9..7de85c9d0 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -912,7 +912,7 @@ void ImGui::ShowTestWindow(bool* opened) static bool track = true; static int track_line = 50, scroll_to_px = 200; ImGui::Checkbox("Track", &track); - ImGui::SameLine(130); track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 9999, "Line %.0f"); + ImGui::SameLine(130); track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 99, "Line %.0f"); bool scroll_to = ImGui::Button("Scroll To"); ImGui::SameLine(130); scroll_to |= ImGui::DragInt("##pos_y", &scroll_to_px, 1.00f, 0, 9999, "y = %.0f px"); if (scroll_to) track = false; @@ -968,6 +968,16 @@ void ImGui::ShowTestWindow(bool* opened) } } ImGui::EndChild(); + float scroll_x_delta = 0.0f; + ImGui::SmallButton("<<"); if (ImGui::IsItemActive()) scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f; + ImGui::SameLine(); ImGui::Text("Scroll from code"); ImGui::SameLine(); + ImGui::SmallButton(">>"); if (ImGui::IsItemActive()) scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f; + if (scroll_x_delta != 0.0f) + { + ImGui::BeginChild("scrolling"); // Demonstrate a trick: you can use Begin to set yourself in the context of another window (here we are already out of your child window) + ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta); + ImGui::End(); + } ImGui::TreePop(); } diff --git a/imgui_internal.h b/imgui_internal.h index 170876c76..b6766e43c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -565,8 +565,8 @@ struct ImGuiWindow ImVec2 WindowPadding; // Window padding at the time of begin. We need to lock it, in particular manipulation of the ShowBorder would have an effect ImGuiID MoveID; // == window->GetID("#MOVE") ImVec2 Scroll; - float ScrollTargetRelY; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change) - float ScrollTargetCenterRatioY; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered + ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change) + ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered bool ScrollbarX, ScrollbarY; ImVec2 ScrollbarSizes; // bool Active; // Set to true on Begin()