mirror of
https://github.com/ocornut/imgui.git
synced 2026-01-11 00:04:24 +00:00
Clipper: added SeekCursorForItem() function, for use when using ImGuiListClipper::Begin(INT_MAX). (#1311)
Tagging #3609 just in case we made a mistake introducing a regression (but tests are passing and have been extended).
This commit is contained in:
parent
74a1854db9
commit
8bab3eab6a
3 changed files with 30 additions and 14 deletions
30
imgui.cpp
30
imgui.cpp
|
|
@ -2911,15 +2911,6 @@ static void ImGuiListClipper_SeekCursorAndSetupPrevLine(float pos_y, float line_
|
|||
}
|
||||
}
|
||||
|
||||
static void ImGuiListClipper_SeekCursorForItem(ImGuiListClipper* clipper, int item_n)
|
||||
{
|
||||
// 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 + data->LossynessOffset + (double)(item_n - data->ItemsFrozen) * clipper->ItemsHeight);
|
||||
ImGuiListClipper_SeekCursorAndSetupPrevLine(pos_y, clipper->ItemsHeight);
|
||||
}
|
||||
|
||||
ImGuiListClipper::ImGuiListClipper()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
|
|
@ -2956,6 +2947,7 @@ void ImGuiListClipper::Begin(int items_count, float items_height)
|
|||
data->Reset(this);
|
||||
data->LossynessOffset = window->DC.CursorStartPosLossyness.y;
|
||||
TempData = data;
|
||||
StartSeekOffsetY = data->LossynessOffset;
|
||||
}
|
||||
|
||||
void ImGuiListClipper::End()
|
||||
|
|
@ -2966,7 +2958,7 @@ void ImGuiListClipper::End()
|
|||
ImGuiContext& g = *Ctx;
|
||||
IMGUI_DEBUG_LOG_CLIPPER("Clipper: End() in '%s'\n", g.CurrentWindow->Name);
|
||||
if (ItemsCount >= 0 && ItemsCount < INT_MAX && DisplayStart >= 0)
|
||||
ImGuiListClipper_SeekCursorForItem(this, ItemsCount);
|
||||
SeekCursorForItem(ItemsCount);
|
||||
|
||||
// Restore temporary buffer and fix back pointers which may be invalidated when nesting
|
||||
IM_ASSERT(data->ListClipper == this);
|
||||
|
|
@ -2990,6 +2982,17 @@ void ImGuiListClipper::IncludeItemsByIndex(int item_begin, int item_end)
|
|||
data->Ranges.push_back(ImGuiListClipperRange::FromIndices(item_begin, item_end));
|
||||
}
|
||||
|
||||
// This is already called while stepping.
|
||||
// The ONLY reason you may want to call this is if you passed INT_MAX to ImGuiListClipper::Begin() because you couldn't step item count beforehand.
|
||||
void ImGuiListClipper::SeekCursorForItem(int item_n)
|
||||
{
|
||||
// - Perform the add and multiply with double to allow seeking through larger ranges.
|
||||
// - StartPosY starts from ItemsFrozen, by adding SeekOffsetY we generally cancel that out (SeekOffsetY == LossynessOffset - ItemsFrozen * ItemsHeight).
|
||||
// - The reason we store SeekOffsetY instead of inferring it, is because we want to allow user to perform Seek after the last step, where ImGuiListClipperData is already done.
|
||||
float pos_y = (float)((double)StartPosY + StartSeekOffsetY + (double)item_n * ItemsHeight);
|
||||
ImGuiListClipper_SeekCursorAndSetupPrevLine(pos_y, ItemsHeight);
|
||||
}
|
||||
|
||||
static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
|
||||
{
|
||||
ImGuiContext& g = *clipper->Ctx;
|
||||
|
|
@ -3053,6 +3056,9 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
|
|||
const int already_submitted = clipper->DisplayEnd;
|
||||
if (calc_clipping)
|
||||
{
|
||||
// Record seek offset, this is so ImGuiListClipper::Seek() can be called after ImGuiListClipperData is done
|
||||
clipper->StartSeekOffsetY = (double)data->LossynessOffset - data->ItemsFrozen * (double)clipper->ItemsHeight;
|
||||
|
||||
if (g.LogEnabled)
|
||||
{
|
||||
// If logging is active, do not perform any clipping
|
||||
|
|
@ -3100,7 +3106,7 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
|
|||
clipper->DisplayStart = ImMax(data->Ranges[data->StepNo].Min, already_submitted);
|
||||
clipper->DisplayEnd = ImMin(data->Ranges[data->StepNo].Max, clipper->ItemsCount);
|
||||
if (clipper->DisplayStart > already_submitted) //-V1051
|
||||
ImGuiListClipper_SeekCursorForItem(clipper, clipper->DisplayStart);
|
||||
clipper->SeekCursorForItem(clipper->DisplayStart);
|
||||
data->StepNo++;
|
||||
if (clipper->DisplayStart == clipper->DisplayEnd && data->StepNo < data->Ranges.Size)
|
||||
continue;
|
||||
|
|
@ -3110,7 +3116,7 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
|
|||
// After the last step: Let the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd),
|
||||
// Advance the cursor to the end of the list and then returns 'false' to end the loop.
|
||||
if (clipper->ItemsCount < INT_MAX)
|
||||
ImGuiListClipper_SeekCursorForItem(clipper, clipper->ItemsCount);
|
||||
clipper->SeekCursorForItem(clipper->ItemsCount);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue