Window, Clipper: store initial precision loss and apply in clipper. (#3609, #3962 + https://github.com/ocornut/imgui_club/issues/20)
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 401adf3..869d1d1 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -72,7 +72,8 @@
by the clipper to display. (#3841)
- Clipper: fixed content height declaration slightly mismatching the value of when not using a clipper.
(an additional ItemSpacing.y was declared, affecting scrollbar range).
-- Clipper: minor and incomplete changes to tame down precision issues on very large ranges (#3609, #3962).
+- Clipper: various and incomplete changes to tame down scrolling and precision issues on very large ranges.
+ Passing an explicit height to the clipper now allows larger ranges. (#3609, #3962).
- Drag and Drop: BeginDragDropSource() with ImGuiDragDropFlags_SourceAllowNullID doesn't lose
tooltip when scrolling. (#143)
- Metrics: Added a node showing windows in submission order and showing the Begin() stack.
diff --git a/imgui.cpp b/imgui.cpp
index f813103..722e84b 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -2350,7 +2350,7 @@
// StartPosY starts from ItemsFrozen hence the subtraction
// Perform the add and multiply with double to allow seeking through larger ranges
ImGuiListClipperData* data = (ImGuiListClipperData*)clipper->TempData;
- float pos_y = (float)((double)clipper->StartPosY + (double)(item_n - data->ItemsFrozen) * clipper->ItemsHeight);
+ float pos_y = (float)((double)clipper->StartPosY + data->LossynessOffset + (double)(item_n - data->ItemsFrozen) * clipper->ItemsHeight);
ImGuiListClipper_SeekCursorAndSetupPrevLine(pos_y, clipper->ItemsHeight);
}
@@ -2388,6 +2388,7 @@
g.ClipperTempData.resize(g.ClipperTempDataStacked, ImGuiListClipperData());
ImGuiListClipperData* data = &g.ClipperTempData[g.ClipperTempDataStacked - 1];
data->Reset(this);
+ data->LossynessOffset = window->DC.CursorStartPosLossyness.y;
TempData = data;
}
@@ -2521,8 +2522,8 @@
for (int i = 0; i < data->Ranges.Size; i++)
if (data->Ranges[i].PosToIndexConvert)
{
- int m1 = (int)(((double)data->Ranges[i].Min - window->DC.CursorPos.y) / ItemsHeight);
- int m2 = (int)((((double)data->Ranges[i].Max - window->DC.CursorPos.y) / ItemsHeight) + 0.999999f);
+ int m1 = (int)(((double)data->Ranges[i].Min - window->DC.CursorPos.y - data->LossynessOffset) / ItemsHeight);
+ int m2 = (int)((((double)data->Ranges[i].Max - window->DC.CursorPos.y - data->LossynessOffset) / ItemsHeight) + 0.999999f);
data->Ranges[i].Min = ImClamp(already_submitted + m1 + data->Ranges[i].PosToIndexOffsetMin, already_submitted, ItemsCount - 1);
data->Ranges[i].Max = ImClamp(already_submitted + m2 + data->Ranges[i].PosToIndexOffsetMax, data->Ranges[i].Min + 1, ItemsCount);
data->Ranges[i].PosToIndexConvert = false;
@@ -6360,7 +6361,13 @@
window->DC.Indent.x = 0.0f + window->WindowPadding.x - window->Scroll.x;
window->DC.GroupOffset.x = 0.0f;
window->DC.ColumnsOffset.x = 0.0f;
- window->DC.CursorStartPos = window->Pos + ImVec2(window->DC.Indent.x + window->DC.ColumnsOffset.x, decoration_up_height + window->WindowPadding.y - window->Scroll.y);
+
+ // Record the loss of precision of CursorStartPos which can happen due to really large scrolling amount.
+ // This is used by clipper to compensate and fix the most common use case of large scroll area. Easy and cheap, next best thing compared to switching everything to double or ImU64.
+ double start_pos_highp_x = (double)window->Pos.x + window->WindowPadding.x - (double)window->Scroll.x + window->DC.ColumnsOffset.x;
+ double start_pos_highp_y = (double)window->Pos.y + window->WindowPadding.y - (double)window->Scroll.y + decoration_up_height;
+ window->DC.CursorStartPos = ImVec2((float)start_pos_highp_x, (float)start_pos_highp_y);
+ window->DC.CursorStartPosLossyness = ImVec2((float)(start_pos_highp_x - window->DC.CursorStartPos.x), (float)(start_pos_highp_y - window->DC.CursorStartPos.y));
window->DC.CursorPos = window->DC.CursorStartPos;
window->DC.CursorPosPrevLine = window->DC.CursorPos;
window->DC.CursorMaxPos = window->DC.CursorStartPos;
diff --git a/imgui.h b/imgui.h
index ab81579..d2da5fe 100644
--- a/imgui.h
+++ b/imgui.h
@@ -64,7 +64,7 @@
// Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.86 WIP"
-#define IMGUI_VERSION_NUM 18514
+#define IMGUI_VERSION_NUM 18515
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE
diff --git a/imgui_internal.h b/imgui_internal.h
index 53af6ae..b5d4904 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1190,6 +1190,7 @@
struct ImGuiListClipperData
{
ImGuiListClipper* ListClipper;
+ float LossynessOffset;
int StepNo;
int ItemsFrozen;
ImVector<ImGuiListClipperRange> Ranges;
@@ -1915,6 +1916,7 @@
ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.)
ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API.
ImVec1 GroupOffset;
+ ImVec2 CursorStartPosLossyness;// Record the loss of precision of CursorStartPos due to really large scrolling amount. This is used by clipper to compensentate and fix the most common use case of large scroll area.
// Keyboard/Gamepad navigation
ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1)