ImGuiFullscreen: Allow smooth scrolling

This commit is contained in:
Stenzek
2024-09-09 21:57:08 +10:00
parent e93dea5ad8
commit 891d5cefbe
9 changed files with 74 additions and 13 deletions

View File

@@ -1303,6 +1303,7 @@ ImGuiStyle::ImGuiStyle()
HoverDelayNormal = 0.40f; // Delay for IsItemHovered(ImGuiHoveredFlags_DelayNormal). "
HoverFlagsForTooltipMouse = ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_AllowWhenDisabled; // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using mouse.
HoverFlagsForTooltipNav = ImGuiHoveredFlags_NoSharedDelay | ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_AllowWhenDisabled; // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using keyboard/gamepad.
ScrollSmooth = 1.0f; // Disabled by default. It's just immediate jump from ScrollExpected to the visual Scroll.
// Default theme
ImGui::StyleColorsDark(this);
@@ -3297,6 +3298,7 @@ static const ImGuiDataVarInfo GStyleVarInfo[] =
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, SeparatorTextBorderSize)}, // ImGuiStyleVar_SeparatorTextBorderSize
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SeparatorTextAlign) }, // ImGuiStyleVar_SeparatorTextAlign
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SeparatorTextPadding) }, // ImGuiStyleVar_SeparatorTextPadding
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ScrollSmooth) }, // ImGuiStyleVar_ScrollSmooth
};
const ImGuiDataVarInfo* ImGui::GetStyleVarInfo(ImGuiStyleVar idx)
@@ -3926,6 +3928,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* ctx, const char* name) : DrawListInst(NUL
IDStack.push_back(ID);
MoveId = GetID("#MOVE");
ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
ScrollExpected = ImVec2(0, 0);
ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f);
AutoFitFramesX = AutoFitFramesY = -1;
AutoPosLastDirection = ImGuiDir_None;
@@ -9524,7 +9527,7 @@ void ImGui::UpdateMouseWheel()
LockWheelingWindow(window, wheel.x);
float max_step = window->InnerRect.GetWidth() * 0.67f;
float scroll_step = ImTrunc(ImMin(2 * window->CalcFontSize(), max_step));
SetScrollX(window, window->Scroll.x - wheel.x * scroll_step);
SetScrollX(window, window->ScrollExpected.x - wheel.x * scroll_step);
g.WheelingWindowScrolledFrame = g.FrameCount;
}
if (do_scroll[ImGuiAxis_Y])
@@ -9532,7 +9535,7 @@ void ImGui::UpdateMouseWheel()
LockWheelingWindow(window, wheel.y);
float max_step = window->InnerRect.GetHeight() * 0.67f;
float scroll_step = ImTrunc(ImMin(5 * window->CalcFontSize(), max_step));
SetScrollY(window, window->Scroll.y - wheel.y * scroll_step);
SetScrollY(window, window->ScrollExpected.y - wheel.y * scroll_step);
g.WheelingWindowScrolledFrame = g.FrameCount;
}
}
@@ -10761,11 +10764,46 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window)
float snap_max = window->ScrollMax[axis] + window->SizeFull[axis] - decoration_size[axis];
scroll_target = CalcScrollEdgeSnap(scroll_target, snap_min, snap_max, window->ScrollTargetEdgeSnapDist[axis], center_ratio);
}
scroll[axis] = scroll_target - center_ratio * (window->SizeFull[axis] - decoration_size[axis]);
window->ScrollExpected[axis] = scroll_target - center_ratio * (window->SizeFull[axis] - decoration_size[axis]);
}
scroll[axis] = IM_ROUND(ImMax(scroll[axis], 0.0f));
// Based on https://github.com/ocornut/imgui/pull/7348
// TODO: Make it not dependent on frame rate, easiest way would be to multiply by delta_time / (1/60).
// Smooth scroll.
// Instead use "Scroll" value in the window, all setters that sets the scroll absolutely now points to
// "ScrollExpected" Here, we take from ScrollTarget (from some functions like ScrollHere + mouse wheel) to set
// the ScrollExpected value Also, Scroll var in window is processed to meet ScrollExpected Value
//
// The formula is pretty simple to generate a smooth scrolling that can be tweaked just by one float value.
//
// The Float is "ImGuiStyleVar_ScrollSmooth". Can be set on the style or via PushStyleVar.
// A Value of 1.0f is just inmediate (transported from ScrollExpected to Scroll).
// A Value higher of 1.0f will make the scrolling smoother.
//
// The ScrollExpected is also clamped (as previously the "Scroll" value) from 0 to sScrollMax
//
// The approach is frame bounded and not time bounded.
// It should be prefereable use a time bounded approach but this is pretty simple so we don't need to add extra
// vars to save a scrolling "start" time to have a delta / deal with posible increments during the scrolling
// itself (restar timer) Anyway it should not be complicated to add but this approach is small, simple, can be
// user or not and works pretty well
//
window->ScrollExpected[axis] = IM_ROUND(ImMax(window->ScrollExpected[axis], 0.0f));
if (!window->Collapsed && !window->SkipItems)
scroll[axis] = ImMin(scroll[axis], window->ScrollMax[axis]);
window->ScrollExpected[axis] = ImMin(window->ScrollExpected[axis], window->ScrollMax[axis]);
ImGuiContext& g = *GImGui;
ImGuiStyle& style = g.Style;
if (scroll[axis] != window->ScrollExpected[axis])
{
const float multiplier = GImGui->IO.DeltaTime / (1.0f / 60.0f);
const float diff = window->ScrollExpected[axis] - scroll[axis];
if (diff > 0)
scroll[axis] += ImMin(diff, (diff / (style.ScrollSmooth * multiplier)));
else
scroll[axis] -= ImMin(-diff, (-diff / (style.ScrollSmooth * multiplier)));
scroll[axis] = window->Appearing ? window->ScrollExpected[axis] : scroll[axis];
}
}
return scroll;
}
@@ -10858,13 +10896,13 @@ ImVec2 ImGui::ScrollToRectEx(ImGuiWindow* window, const ImRect& item_rect, ImGui
float ImGui::GetScrollX()
{
ImGuiWindow* window = GImGui->CurrentWindow;
return window->Scroll.x;
return window->ScrollExpected.x;
}
float ImGui::GetScrollY()
{
ImGuiWindow* window = GImGui->CurrentWindow;
return window->Scroll.y;
return window->ScrollExpected.y;
}
float ImGui::GetScrollMaxX()

View File

@@ -933,9 +933,9 @@ void ImGui::Scrollbar(ImGuiAxis axis)
}
float size_visible = window->InnerRect.Max[axis] - window->InnerRect.Min[axis];
float size_contents = window->ContentSize[axis] + window->WindowPadding[axis] * 2.0f;
ImS64 scroll = (ImS64)window->Scroll[axis];
ImS64 scroll = (ImS64)window->ScrollExpected[axis];
ScrollbarEx(bb, id, axis, &scroll, (ImS64)size_visible, (ImS64)size_contents, rounding_corners);
window->Scroll[axis] = (float)scroll;
window->ScrollExpected[axis] = (float)scroll;
}
// Vertical/Horizontal scrollbar