From 9e3f8adfac83d6516780505bdaaaf1c071b8b972 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 8 Feb 2015 13:44:09 +0000 Subject: [PATCH] Added CalcListClipping() helper. --- imgui.cpp | 41 ++++++++++++++++++++++++++++++++++++++++- imgui.h | 1 + 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 59c50755..10688cd1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -604,7 +604,8 @@ static inline float ImMin(float lhs, float rhs) static inline float ImMax(float lhs, float rhs) { return lhs >= rhs ? lhs : rhs; } static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMin(lhs.x,rhs.x), ImMin(lhs.y,rhs.y)); } static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMax(lhs.x,rhs.x), ImMax(lhs.y,rhs.y)); } -static inline float ImClamp(float f, float mn, float mx) { return (f < mn) ? mn : (f > mx) ? mx : f; } +static inline int ImClamp(int v, int mn, int mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } +static inline float ImClamp(float v, float mn, float mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } static inline ImVec2 ImClamp(const ImVec2& f, const ImVec2& mn, ImVec2 mx) { return ImVec2(ImClamp(f.x,mn.x,mx.x), ImClamp(f.y,mn.y,mx.y)); } static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; } static inline float ImLerp(float a, float b, float t) { return a + (b - a) * t; } @@ -2174,6 +2175,44 @@ ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_tex return text_size; } +// Helper to calculate clipping of large list of evenly sized items. +// If you are displaying thousands of items and you have a random access to the list, you can perform clipping yourself to save on CPU. +// { +// float item_height = ImGui::GetTextLineHeightWithSpacing(); +// int display_start, display_end; +// ImGui::CalcListClipping(count, item_height, &display_start, &display_end); // calculate how many to clip/display +// ImGui::SetCursorPosY(ImGui::GetCursorPosY() + (display_start) * item_height); // advance cursor +// for (int i = display_start; i < display_end; i++) // display only visible items +// // TODO: display visible item +// ImGui::SetCursorPosY(ImGui::GetCursorPosY() + (count - display_end) * item_height); // advance cursor +// } +void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end) +{ + ImGuiState& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + + if (g.LogEnabled) + { + // If logging is active, do not perform any clipping + *out_items_display_start = 0; + *out_items_display_end = items_count; + return; + } + + const ImVec2 pos = window->DC.CursorPos; + const ImVec4 clip_rect = window->ClipRectStack.back(); + const float clip_y1 = clip_rect.y; + const float clip_y2 = clip_rect.w; + + int start = (int)((clip_y1 - pos.y) / items_height); + int end = (int)((clip_y2 - pos.y) / items_height); + start = ImClamp(start, 0, items_count); + end = ImClamp(end + 1, start, items_count); + + *out_items_display_start = start; + *out_items_display_end = end; +} + // Find window given position, search front-to-back static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs) { diff --git a/imgui.h b/imgui.h index fed27ab0..edb03ebc 100644 --- a/imgui.h +++ b/imgui.h @@ -331,6 +331,7 @@ namespace ImGui IMGUI_API int GetFrameCount(); IMGUI_API const char* GetStyleColName(ImGuiCol idx); IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); + IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // helper to manually clip large list of items. see comments in implementation. IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4& in); IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v);