Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/wolfpld/tracy.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/imgui
diff options
context:
space:
mode:
authorBartosz Taudul <wolf.pld@gmail.com>2020-09-03 19:19:58 +0300
committerBartosz Taudul <wolf.pld@gmail.com>2020-09-03 19:19:58 +0300
commit3e34b3832afc7466a04e6b4781cb472e1930edac (patch)
tree755978b8f35a9db3c56b7e4ad142cc35506ab3c1 /imgui
parent023c96fbc45c750431e96731ca7e9c71a5401e51 (diff)
Fix https://github.com/ocornut/imgui/issues/3452
Diffstat (limited to 'imgui')
-rw-r--r--imgui/imgui.cpp104
-rw-r--r--imgui/imgui_internal.h9
2 files changed, 62 insertions, 51 deletions
diff --git a/imgui/imgui.cpp b/imgui/imgui.cpp
index 2c1b7e70..78edb1d8 100644
--- a/imgui/imgui.cpp
+++ b/imgui/imgui.cpp
@@ -8070,21 +8070,42 @@ void ImGui::EndGroup()
// [SECTION] SCROLLING
//-----------------------------------------------------------------------------
+// Helper to snap on edges when aiming at an item very close to the edge,
+// So the difference between WindowPadding and ItemSpacing will be in the visible area after scrolling.
+// When we refactor the scrolling API this may be configurable with a flag?
+// Note that the effect for this won't be visible on X axis with default Style settings as WindowPadding.x == ItemSpacing.x by default.
+static float CalcScrollEdgeSnap(float target, float snap_min, float snap_max, float snap_threshold, float center_ratio)
+{
+ if (target <= snap_min + snap_threshold)
+ return ImLerp(snap_min, target, center_ratio);
+ if (target >= snap_max - snap_threshold)
+ return ImLerp(target, snap_max, center_ratio);
+ return target;
+}
+
static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window)
{
ImVec2 scroll = window->Scroll;
if (window->ScrollTarget.x < FLT_MAX)
{
- float cr_x = window->ScrollTargetCenterRatio.x;
- float target_x = window->ScrollTarget.x;
- scroll.x = target_x - cr_x * (window->SizeFull.x - window->ScrollbarSizes.x);
+ float center_x_ratio = window->ScrollTargetCenterRatio.x;
+ float scroll_target_x = window->ScrollTarget.x;
+ float snap_x_min = 0.0f;
+ float snap_x_max = window->ScrollMax.x + window->Size.x;
+ if (window->ScrollTargetEdgeSnapDist.x > 0.0f)
+ scroll_target_x = CalcScrollEdgeSnap(scroll_target_x, snap_x_min, snap_x_max, window->ScrollTargetEdgeSnapDist.x, center_x_ratio);
+ scroll.x = scroll_target_x - center_x_ratio * (window->SizeFull.x - window->ScrollbarSizes.x);
}
if (window->ScrollTarget.y < FLT_MAX)
{
float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight();
- float cr_y = window->ScrollTargetCenterRatio.y;
- float target_y = window->ScrollTarget.y;
- scroll.y = target_y - cr_y * (window->SizeFull.y - window->ScrollbarSizes.y - decoration_up_height);
+ float center_y_ratio = window->ScrollTargetCenterRatio.y;
+ float scroll_target_y = window->ScrollTarget.y;
+ float snap_y_min = 0.0f;
+ float snap_y_max = window->ScrollMax.y + window->Size.y - decoration_up_height;
+ if (window->ScrollTargetEdgeSnapDist.y > 0.0f)
+ scroll_target_y = CalcScrollEdgeSnap(scroll_target_y, snap_y_min, snap_y_max, window->ScrollTargetEdgeSnapDist.y, center_y_ratio);
+ scroll.y = scroll_target_y - center_y_ratio * (window->SizeFull.y - window->ScrollbarSizes.y - decoration_up_height);
}
scroll.x = IM_FLOOR(ImMax(scroll.x, 0.0f));
scroll.y = IM_FLOOR(ImMax(scroll.y, 0.0f));
@@ -8150,47 +8171,57 @@ float ImGui::GetScrollMaxY()
return window->ScrollMax.y;
}
-void ImGui::SetScrollX(float scroll_x)
+void ImGui::SetScrollX(ImGuiWindow* window, float scroll_x)
{
- ImGuiWindow* window = GetCurrentWindow();
window->ScrollTarget.x = scroll_x;
window->ScrollTargetCenterRatio.x = 0.0f;
+ window->ScrollTargetEdgeSnapDist.x = 0.0f;
}
-void ImGui::SetScrollY(float scroll_y)
+void ImGui::SetScrollY(ImGuiWindow* window, float scroll_y)
{
- ImGuiWindow* window = GetCurrentWindow();
window->ScrollTarget.y = scroll_y;
window->ScrollTargetCenterRatio.y = 0.0f;
+ window->ScrollTargetEdgeSnapDist.y = 0.0f;
}
-void ImGui::SetScrollX(ImGuiWindow* window, float new_scroll_x)
+void ImGui::SetScrollX(float scroll_x)
{
- window->ScrollTarget.x = new_scroll_x;
- window->ScrollTargetCenterRatio.x = 0.0f;
+ ImGuiContext& g = *GImGui;
+ SetScrollX(g.CurrentWindow, scroll_x);
}
-void ImGui::SetScrollY(ImGuiWindow* window, float new_scroll_y)
+void ImGui::SetScrollY(float scroll_y)
{
- window->ScrollTarget.y = new_scroll_y;
- window->ScrollTargetCenterRatio.y = 0.0f;
+ ImGuiContext& g = *GImGui;
+ SetScrollY(g.CurrentWindow, scroll_y);
}
-// Note that a local position will vary depending on initial scroll value
-// We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size
+// Note that a local position will vary depending on initial scroll value,
+// This is a little bit confusing so bear with us:
+// - local_pos = (absolution_pos - window->Pos)
+// - So local_x/local_y are 0.0f for a position at the upper-left corner of a window,
+// and generally local_x/local_y are >(padding+decoration) && <(size-padding-decoration) when in the visible area.
+// - They mostly exists because of legacy API.
+// Following the rules above, when trying to work with scrolling code, consider that:
+// - SetScrollFromPosY(0.0f) == SetScrollY(0.0f + scroll.y) == has no effect!
+// - SetScrollFromPosY(-scroll.y) == SetScrollY(-scroll.y + scroll.y) == SetScrollY(0.0f) == reset scroll. Of course writing SetScrollY(0.0f) directly then makes more sense
+// We store a target position so centering and clamping can occur on the next frame when we are guaranteed to have a known window size
void ImGui::SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio)
{
IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f);
- window->ScrollTarget.x = IM_FLOOR(local_x + window->Scroll.x);
+ window->ScrollTarget.x = IM_FLOOR(local_x + window->Scroll.x); // Convert local position to scroll offset
window->ScrollTargetCenterRatio.x = center_x_ratio;
+ window->ScrollTargetEdgeSnapDist.x = 0.0f;
}
void ImGui::SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio)
{
IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f);
local_y -= window->TitleBarHeight() + window->MenuBarHeight(); // FIXME: Would be nice to have a more standardized access to our scrollable/client rect
- window->ScrollTarget.y = IM_FLOOR(local_y + window->Scroll.y);
+ window->ScrollTarget.y = IM_FLOOR(local_y + window->Scroll.y); // Convert local position to scroll offset
window->ScrollTargetCenterRatio.y = center_y_ratio;
+ window->ScrollTargetEdgeSnapDist.y = 0.0f;
}
void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio)
@@ -8205,34 +8236,17 @@ void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio)
SetScrollFromPosY(g.CurrentWindow, local_y, center_y_ratio);
}
-// Tweak: snap on edges when aiming at an item very close to the edge,
-// So the difference between WindowPadding and ItemSpacing will be in the visible area after scrolling.
-// When we refactor the scrolling API this may be configurable with a flag?
-// Note that the effect for this won't be visible on X axis with default Style settings as WindowPadding.x == ItemSpacing.x by default.
-static float CalcScrollSnap(float target, float snap_min, float snap_max, float snap_threshold, float center_ratio)
-{
- if (target <= snap_min + snap_threshold)
- return ImLerp(snap_min, target, center_ratio);
- if (target >= snap_max - snap_threshold)
- return ImLerp(target, snap_max, center_ratio);
- return target;
-}
-
// center_x_ratio: 0.0f left of last item, 0.5f horizontal center of last item, 1.0f right of last item.
void ImGui::SetScrollHereX(float center_x_ratio)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
float spacing_x = g.Style.ItemSpacing.x;
- float target_x = ImLerp(window->DC.LastItemRect.Min.x - spacing_x, window->DC.LastItemRect.Max.x + spacing_x, center_x_ratio);
+ float target_pos_x = ImLerp(window->DC.LastItemRect.Min.x - spacing_x, window->DC.LastItemRect.Max.x + spacing_x, center_x_ratio);
+ SetScrollFromPosX(window, target_pos_x - window->Pos.x, center_x_ratio); // Convert from absolute to local pos
// Tweak: snap on edges when aiming at an item very close to the edge
- const float snap_x_threshold = ImMax(0.0f, window->WindowPadding.x - spacing_x);
- const float snap_x_min = window->DC.CursorStartPos.x - window->WindowPadding.x;
- const float snap_x_max = window->DC.CursorStartPos.x + window->ContentSize.x + window->WindowPadding.x;
- target_x = CalcScrollSnap(target_x, snap_x_min, snap_x_max, snap_x_threshold, center_x_ratio);
-
- SetScrollFromPosX(window, target_x - window->Pos.x, center_x_ratio);
+ window->ScrollTargetEdgeSnapDist.x = ImMax(0.0f, window->WindowPadding.x - spacing_x);
}
// center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item.
@@ -8241,15 +8255,11 @@ void ImGui::SetScrollHereY(float center_y_ratio)
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
float spacing_y = g.Style.ItemSpacing.y;
- float target_y = ImLerp(window->DC.CursorPosPrevLine.y - spacing_y, window->DC.CursorPosPrevLine.y + window->DC.PrevLineSize.y + spacing_y, center_y_ratio);
+ float target_pos_y = ImLerp(window->DC.CursorPosPrevLine.y - spacing_y, window->DC.CursorPosPrevLine.y + window->DC.PrevLineSize.y + spacing_y, center_y_ratio);
+ SetScrollFromPosY(window, target_pos_y - window->Pos.y, center_y_ratio); // Convert from absolute to local pos
// Tweak: snap on edges when aiming at an item very close to the edge
- const float snap_y_threshold = ImMax(0.0f, window->WindowPadding.y - spacing_y);
- const float snap_y_min = window->DC.CursorStartPos.y - window->WindowPadding.y;
- const float snap_y_max = window->DC.CursorStartPos.y + window->ContentSize.y + window->WindowPadding.y;
- target_y = CalcScrollSnap(target_y, snap_y_min, snap_y_max, snap_y_threshold, center_y_ratio);
-
- SetScrollFromPosY(window, target_y - window->Pos.y, center_y_ratio);
+ window->ScrollTargetEdgeSnapDist.y = ImMax(0.0f, window->WindowPadding.y - spacing_y);
}
//-----------------------------------------------------------------------------
diff --git a/imgui/imgui_internal.h b/imgui/imgui_internal.h
index 3f769602..6be0a711 100644
--- a/imgui/imgui_internal.h
+++ b/imgui/imgui_internal.h
@@ -1769,6 +1769,7 @@ struct IMGUI_API ImGuiWindow
ImVec2 ScrollMax;
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
+ ImVec2 ScrollTargetEdgeSnapDist; // 0.0f = no snapping, >0.0f snapping threshold
ImVec2 ScrollbarSizes; // Size taken by each scrollbars on their smaller axis. Pay attention! ScrollbarSizes.x == width of the vertical scrollbar, ScrollbarSizes.y = height of the horizontal scrollbar.
bool ScrollbarX, ScrollbarY; // Are scrollbars visible?
bool ViewportOwned;
@@ -2036,10 +2037,10 @@ namespace ImGui
// Scrolling
IMGUI_API void SetNextWindowScroll(const ImVec2& scroll); // Use -1.0f on one axis to leave as-is
- IMGUI_API void SetScrollX(ImGuiWindow* window, float new_scroll_x);
- IMGUI_API void SetScrollY(ImGuiWindow* window, float new_scroll_y);
- IMGUI_API void SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio = 0.5f);
- IMGUI_API void SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio = 0.5f);
+ IMGUI_API void SetScrollX(ImGuiWindow* window, float scroll_x);
+ IMGUI_API void SetScrollY(ImGuiWindow* window, float scroll_y);
+ IMGUI_API void SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio);
+ IMGUI_API void SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio);
IMGUI_API ImVec2 ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_rect);
// Basic Accessors