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
@ -77,6 +77,10 @@ Other changes:
|
||||
Disabling this was previously possible for Selectable() via a direct flag but not for MenuItem().
|
||||
(#1379, #1468, #2200, #4936, #5216, #7302, #7573)
|
||||
- This was mostly all previously in imgui_internal.h.
|
||||
- Clipper: added SeekCursorForItem() function. When using ImGuiListClipper::Begin(INT_MAX) you can
|
||||
can use the clipper without knowing the amount of items beforehand. (#1311)
|
||||
In this situation, call ImGuiListClipper::SeekCursorForItem(items_count) as the end of your iteration
|
||||
loop to position the layout cursor correctly. This is done automatically if provided a count to Begin().
|
||||
- Style: close button and collapse/window-menu button hover highlight made rectangular instead of round.
|
||||
- Debug Tools: Added IMGUI_DEBUG_LOG(), ImGui::DebugLog() in public API. (#5855)
|
||||
Debug log entries add a imgui frame counter prefix + are redirected to ShowDebugLogWindow() and
|
||||
|
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;
|
||||
}
|
||||
|
10
imgui.h
10
imgui.h
@ -28,7 +28,7 @@
|
||||
// Library Version
|
||||
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
|
||||
#define IMGUI_VERSION "1.91.0 WIP"
|
||||
#define IMGUI_VERSION_NUM 19094
|
||||
#define IMGUI_VERSION_NUM 19095
|
||||
#define IMGUI_HAS_TABLE
|
||||
|
||||
/*
|
||||
@ -2601,9 +2601,10 @@ struct ImGuiListClipper
|
||||
int ItemsCount; // [Internal] Number of items
|
||||
float ItemsHeight; // [Internal] Height of item after a first step and item submission can calculate it
|
||||
float StartPosY; // [Internal] Cursor position at the time of Begin() or after table frozen rows are all processed
|
||||
double StartSeekOffsetY; // [Internal] Account for frozen rows in a table and initial loss of precision in very large windows.
|
||||
void* TempData; // [Internal] Internal data
|
||||
|
||||
// items_count: Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step)
|
||||
// items_count: Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step, and you can call SeekCursorForItem() manually if you need)
|
||||
// items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing().
|
||||
IMGUI_API ImGuiListClipper();
|
||||
IMGUI_API ~ImGuiListClipper();
|
||||
@ -2616,6 +2617,11 @@ struct ImGuiListClipper
|
||||
inline void IncludeItemByIndex(int item_index) { IncludeItemsByIndex(item_index, item_index + 1); }
|
||||
IMGUI_API void IncludeItemsByIndex(int item_begin, int item_end); // item_end is exclusive e.g. use (42, 42+1) to make item 42 never clipped.
|
||||
|
||||
// Seek cursor toward given item. This is automatically called while stepping.
|
||||
// - The only reason to call this is: you can use ImGuiListClipper::Begin(INT_MAX) if you don't know item count ahead of time.
|
||||
// - In this case, after all steps are done, you'll want to call SeekCursorForItem(item_count).
|
||||
IMGUI_API void SeekCursorForItem(int item_index);
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
inline void IncludeRangeByIndices(int item_begin, int item_end) { IncludeItemsByIndex(item_begin, item_end); } // [renamed in 1.89.9]
|
||||
inline void ForceDisplayRangeByIndices(int item_begin, int item_end) { IncludeItemsByIndex(item_begin, item_end); } // [renamed in 1.89.6]
|
||||
|
Loading…
Reference in New Issue
Block a user