From 2af8e0238cb5e26a1d8b9a1f04cee85c15e40ad0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 8 Mar 2015 12:04:38 +0000 Subject: [PATCH] Added GetScrollPosY(), GetScrollMaxY() (mentioned in #150) --- imgui.cpp | 45 ++++++++++++++++++++++++++++++--------------- imgui.h | 2 ++ 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c61df119..8e18d01f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1122,7 +1122,8 @@ struct ImGuiWindow ImVec2 Pos; // Position rounded-up to nearest pixel ImVec2 Size; // Current size (==SizeFull or collapsed title bar size) ImVec2 SizeFull; // Size when non collapsed - ImVec2 SizeContentsFit; // Size of contents (extents reach by the drawing cursor) - may not fit within Size. + ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame + ImVec2 SizeContentsCurrent; // Size of contents, currently extending float ScrollY; float NextScrollY; bool ScrollbarY; @@ -1464,7 +1465,7 @@ ImGuiWindow::ImGuiWindow(const char* name) Flags = 0; PosFloat = Pos = ImVec2(0.0f, 0.0f); Size = SizeFull = ImVec2(0.0f, 0.0f); - SizeContentsFit = ImVec2(0.0f, 0.0f); + SizeContents = SizeContentsCurrent = ImVec2(0.0f, 0.0f); ScrollY = 0.0f; NextScrollY = 0.0f; ScrollbarY = false; @@ -2802,6 +2803,10 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size, float bg window->LastFrameDrawn = current_frame; window->ClipRectStack.resize(0); + // Reset contents size for auto-fitting + window->SizeContents = window->SizeContentsCurrent; + window->SizeContentsCurrent = ImVec2(0.0f, 0.0f); + if (flags & ImGuiWindowFlags_ChildWindow) { parent_window->DC.ChildWindows.push_back(window); @@ -2896,7 +2901,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size, float bg window->ScrollY = window->NextScrollY; window->ScrollY = ImMax(window->ScrollY, 0.0f); if (!window->Collapsed && !window->SkipItems) - window->ScrollY = ImMin(window->ScrollY, ImMax(0.0f, (float)window->SizeContentsFit.y - window->SizeFull.y)); + window->ScrollY = ImMin(window->ScrollY, ImMax(0.0f, (float)window->SizeContents.y - window->SizeFull.y)); window->NextScrollY = window->ScrollY; // At this point we don't have a clipping rectangle setup yet, so we can test and draw in title bar @@ -2936,12 +2941,12 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size, float bg if ((window->Flags & ImGuiWindowFlags_Tooltip) != 0) { // Tooltip always resize. We keep the spacing symmetric on both axises for aesthetic purpose. - const ImVec2 size_auto_fit = window->SizeContentsFit + style.WindowPadding - ImVec2(0.0f, style.ItemSpacing.y); + const ImVec2 size_auto_fit = window->SizeContents + style.WindowPadding - ImVec2(0.0f, style.ItemSpacing.y); window->SizeFull = size_auto_fit; } else { - const ImVec2 size_auto_fit = ImClamp(window->SizeContentsFit + style.AutoFitPadding, style.WindowMinSize, ImMax(style.WindowMinSize, g.IO.DisplaySize - style.AutoFitPadding)); + const ImVec2 size_auto_fit = ImClamp(window->SizeContents + style.AutoFitPadding, style.WindowMinSize, ImMax(style.WindowMinSize, g.IO.DisplaySize - style.AutoFitPadding)); if ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0) { // Don't continuously mark settings as dirty, the size of the window doesn't need to be stored. @@ -2989,7 +2994,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size, float bg } // Scrollbar - window->ScrollbarY = (window->SizeContentsFit.y > window->Size.y) && !(window->Flags & ImGuiWindowFlags_NoScrollbar); + window->ScrollbarY = (window->SizeContents.y > window->Size.y) && !(window->Flags & ImGuiWindowFlags_NoScrollbar); // Window background if (bg_alpha > 0.0f) @@ -3025,7 +3030,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size, float bg scrollbar_bb.Expand(ImVec2(-3,-3)); const float scrollbar_height = scrollbar_bb.GetHeight(); - const float grab_size_y_norm = ImSaturate(window->Size.y / ImMax(window->SizeContentsFit.y, window->Size.y)); + const float grab_size_y_norm = ImSaturate(window->Size.y / ImMax(window->SizeContents.y, window->Size.y)); const float grab_size_y_pixels = ImMax(style.GrabMinSize, scrollbar_height * grab_size_y_norm); // Handle input right away (none of the code above is relying on scrolling position) @@ -3039,13 +3044,13 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size, float bg { g.HoveredId = scrollbar_id; const float pos_y_norm = ImSaturate((g.IO.MousePos.y - (scrollbar_bb.Min.y + grab_size_y_pixels*0.5f)) / (scrollbar_height - grab_size_y_pixels)); - window->ScrollY = (float)(int)(pos_y_norm * (window->SizeContentsFit.y - window->Size.y)); + window->ScrollY = (float)(int)(pos_y_norm * (window->SizeContents.y - window->Size.y)); window->NextScrollY = window->ScrollY; } } // Normalized height of the grab - const float pos_y_norm = ImSaturate(window->ScrollY / ImMax(0.0f, window->SizeContentsFit.y - window->Size.y)); + const float pos_y_norm = ImSaturate(window->ScrollY / ImMax(0.0f, window->SizeContents.y - window->Size.y)); const ImU32 grab_col = window->Color(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab); window->DrawList->AddRectFilled( ImVec2(scrollbar_bb.Min.x, ImLerp(scrollbar_bb.Min.y, scrollbar_bb.Max.y - grab_size_y_pixels, pos_y_norm)), @@ -3095,8 +3100,6 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size, float bg window->DC.TreeDepth = 0; window->DC.StateStorage = &window->StateStorage; - // Reset contents size for auto-fitting - window->SizeContentsFit = ImVec2(0.0f, 0.0f); if (window->AutoFitFrames > 0) window->AutoFitFrames--; @@ -3677,21 +3680,21 @@ void ImGui::SetCursorPos(const ImVec2& pos) { ImGuiWindow* window = GetCurrentWindow(); window->DC.CursorPos = window->Pos + pos; - window->SizeContentsFit = ImMax(window->SizeContentsFit, pos + ImVec2(0.0f, window->ScrollY)); + window->SizeContentsCurrent = ImMax(window->SizeContentsCurrent, pos + ImVec2(0.0f, window->ScrollY)); } void ImGui::SetCursorPosX(float x) { ImGuiWindow* window = GetCurrentWindow(); window->DC.CursorPos.x = window->Pos.x + x; - window->SizeContentsFit.x = ImMax(window->SizeContentsFit.x, x); + window->SizeContentsCurrent.x = ImMax(window->SizeContentsCurrent.x, x); } void ImGui::SetCursorPosY(float y) { ImGuiWindow* window = GetCurrentWindow(); window->DC.CursorPos.y = window->Pos.y + y; - window->SizeContentsFit.y = ImMax(window->SizeContentsFit.y, y + window->ScrollY); + window->SizeContentsCurrent.y = ImMax(window->SizeContentsCurrent.y, y + window->ScrollY); } ImVec2 ImGui::GetCursorScreenPos() @@ -3706,6 +3709,18 @@ void ImGui::SetCursorScreenPos(const ImVec2& screen_pos) window->DC.CursorPos = screen_pos; } +float ImGui::GetScrollPosY() +{ + ImGuiWindow* window = GetCurrentWindow(); + return window->ScrollY; +} + +float ImGui::GetScrollMaxY() +{ + ImGuiWindow* window = GetCurrentWindow(); + return window->SizeContents.y - window->SizeFull.y; +} + void ImGui::SetScrollPosHere() { ImGuiWindow* window = GetCurrentWindow(); @@ -6413,7 +6428,7 @@ static void ItemSize(ImVec2 size, ImVec2* adjust_vertical_offset) window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y); window->DC.CursorPos = ImVec2((float)(int)(window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX), (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y)); - window->SizeContentsFit = ImMax(window->SizeContentsFit, ImVec2(window->DC.CursorPosPrevLine.x - window->Pos.x, window->DC.CursorPos.y + window->ScrollY - window->Pos.y)); + window->SizeContentsCurrent = ImMax(window->SizeContentsCurrent, ImVec2(window->DC.CursorPosPrevLine.x - window->Pos.x, window->DC.CursorPos.y + window->ScrollY - window->Pos.y)); window->DC.PrevLineHeight = line_height; window->DC.CurrentLineHeight = 0.0f; diff --git a/imgui.h b/imgui.h index 9d96ae57..0bcc5e70 100644 --- a/imgui.h +++ b/imgui.h @@ -190,6 +190,8 @@ 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 + IMGUI_API float GetScrollPosY(); // get scrolling position (0..GetScrollMaxY()) + IMGUI_API float GetScrollMaxY(); // get maximum scrolling position == ContentSize.Y - WindowSize.Y IMGUI_API void SetScrollPosHere(); // adjust scrolling position to center into the current cursor position. IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. IMGUI_API void SetStateStorage(ImGuiStorage* tree); // replace tree state storage with our own (if you want to manipulate it yourself, typically clear subsection of it).