Skip to content

Commit

Permalink
Window, Clipper: store initial precision loss and apply in clipper. (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ocornut committed Dec 6, 2021
1 parent 6e141a9 commit a76bc52
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 6 deletions.
3 changes: 2 additions & 1 deletion docs/CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ Other Changes:
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.
Expand Down
15 changes: 11 additions & 4 deletions imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2350,7 +2350,7 @@ static void ImGuiListClipper_SeekCursorForItem(ImGuiListClipper* clipper, int it
// 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);
}

Expand Down Expand Up @@ -2388,6 +2388,7 @@ void ImGuiListClipper::Begin(int items_count, float items_height)
g.ClipperTempData.resize(g.ClipperTempDataStacked, ImGuiListClipperData());
ImGuiListClipperData* data = &g.ClipperTempData[g.ClipperTempDataStacked - 1];
data->Reset(this);
data->LossynessOffset = window->DC.CursorStartPosLossyness.y;
TempData = data;
}

Expand Down Expand Up @@ -2521,8 +2522,8 @@ bool ImGuiListClipper::Step()
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;
Expand Down Expand Up @@ -6360,7 +6361,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
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;
Expand Down
2 changes: 1 addition & 1 deletion imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Index of this file:
// 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

Expand Down
2 changes: 2 additions & 0 deletions imgui_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1190,6 +1190,7 @@ struct ImGuiListClipperRange
struct ImGuiListClipperData
{
ImGuiListClipper* ListClipper;
float LossynessOffset;
int StepNo;
int ItemsFrozen;
ImVector<ImGuiListClipperRange> Ranges;
Expand Down Expand Up @@ -1915,6 +1916,7 @@ struct IMGUI_API ImGuiWindowTempData
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)
Expand Down

0 comments on commit a76bc52

Please sign in to comment.