Window, Clipper: store initial precision loss and apply in clipper. (#3609, #3962 + https://github.com/ocornut/imgui_club/issues/20)

This commit is contained in:
ocornut 2021-12-06 12:48:21 +01:00
parent 6e141a9cae
commit a76bc52da5
4 changed files with 16 additions and 6 deletions

View File

@ -72,7 +72,8 @@ Other Changes:
by the clipper to display. (#3841) by the clipper to display. (#3841)
- Clipper: fixed content height declaration slightly mismatching the value of when not using a clipper. - Clipper: fixed content height declaration slightly mismatching the value of when not using a clipper.
(an additional ItemSpacing.y was declared, affecting scrollbar range). (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 - Drag and Drop: BeginDragDropSource() with ImGuiDragDropFlags_SourceAllowNullID doesn't lose
tooltip when scrolling. (#143) tooltip when scrolling. (#143)
- Metrics: Added a node showing windows in submission order and showing the Begin() stack. - Metrics: Added a node showing windows in submission order and showing the Begin() stack.

View File

@ -2350,7 +2350,7 @@ static void ImGuiListClipper_SeekCursorForItem(ImGuiListClipper* clipper, int it
// StartPosY starts from ItemsFrozen hence the subtraction // StartPosY starts from ItemsFrozen hence the subtraction
// Perform the add and multiply with double to allow seeking through larger ranges // Perform the add and multiply with double to allow seeking through larger ranges
ImGuiListClipperData* data = (ImGuiListClipperData*)clipper->TempData; 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); ImGuiListClipper_SeekCursorAndSetupPrevLine(pos_y, clipper->ItemsHeight);
} }
@ -2388,6 +2388,7 @@ void ImGuiListClipper::Begin(int items_count, float items_height)
g.ClipperTempData.resize(g.ClipperTempDataStacked, ImGuiListClipperData()); g.ClipperTempData.resize(g.ClipperTempDataStacked, ImGuiListClipperData());
ImGuiListClipperData* data = &g.ClipperTempData[g.ClipperTempDataStacked - 1]; ImGuiListClipperData* data = &g.ClipperTempData[g.ClipperTempDataStacked - 1];
data->Reset(this); data->Reset(this);
data->LossynessOffset = window->DC.CursorStartPosLossyness.y;
TempData = data; TempData = data;
} }
@ -2521,8 +2522,8 @@ bool ImGuiListClipper::Step()
for (int i = 0; i < data->Ranges.Size; i++) for (int i = 0; i < data->Ranges.Size; i++)
if (data->Ranges[i].PosToIndexConvert) if (data->Ranges[i].PosToIndexConvert)
{ {
int m1 = (int)(((double)data->Ranges[i].Min - window->DC.CursorPos.y) / ItemsHeight); 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) / ItemsHeight) + 0.999999f); 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].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].Max = ImClamp(already_submitted + m2 + data->Ranges[i].PosToIndexOffsetMax, data->Ranges[i].Min + 1, ItemsCount);
data->Ranges[i].PosToIndexConvert = false; data->Ranges[i].PosToIndexConvert = false;
@ -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.Indent.x = 0.0f + window->WindowPadding.x - window->Scroll.x;
window->DC.GroupOffset.x = 0.0f; window->DC.GroupOffset.x = 0.0f;
window->DC.ColumnsOffset.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.CursorPos = window->DC.CursorStartPos;
window->DC.CursorPosPrevLine = window->DC.CursorPos; window->DC.CursorPosPrevLine = window->DC.CursorPos;
window->DC.CursorMaxPos = window->DC.CursorStartPos; window->DC.CursorMaxPos = window->DC.CursorStartPos;

View File

@ -64,7 +64,7 @@ Index of this file:
// Version // 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) // (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 "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_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE

View File

@ -1190,6 +1190,7 @@ struct ImGuiListClipperRange
struct ImGuiListClipperData struct ImGuiListClipperData
{ {
ImGuiListClipper* ListClipper; ImGuiListClipper* ListClipper;
float LossynessOffset;
int StepNo; int StepNo;
int ItemsFrozen; int ItemsFrozen;
ImVector<ImGuiListClipperRange> Ranges; ImVector<ImGuiListClipperRange> Ranges;
@ -1915,6 +1916,7 @@ struct IMGUI_API ImGuiWindowTempData
ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) 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 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; 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 // Keyboard/Gamepad navigation
ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1)