The first sweep matched a character class that swallowed the digit, so a bare B1 slipped through while B1-2 was caught. Searching the whole A-Z space instead of guessing prefixes turned up 130-odd more: B0 through B6, C2, C3, D1, H2, M6, P7, P8, T2, W2, plus GP-04, KB-01, OD-1, PM-1, PM-3, SEC-01, TR-4, TR-7, UI-11, UI-12, XC-8 and API-3. Kept deliberately: 41 B4 01 is a byte signature, "N0" a format string, #L119-L128 a source anchor, LS4/LS6 are linkshells, and A=FF B=0C G=41 R=C2 explains a colour-channel order. Those look like codes and are not. Also translated the eight German comments left in the theme files and ImGuiUtil. Seven of them described what a palette does to which channel, which is worth reading -- just not in a second language in an otherwise English codebase.
78 lines
2.6 KiB
C#
78 lines
2.6 KiB
C#
using System.Collections.Generic;
|
|
|
|
namespace HellionChat.Ui.Components;
|
|
|
|
// Variable-height clip plan. ImGuiListClipper needs a constant
|
|
// row height, and since v1.10.0 neither density has one (compact rows wrap
|
|
// too), so both compute a plan from the cached per-row heights: a lead dummy
|
|
// for the rows above
|
|
// the viewport, the [first..last] index range that overlaps the viewport, and
|
|
// an end dummy for the rows below. This is the prefix-sum analogue of
|
|
// OtterGui's GetNecessarySkips, but for non-uniform heights — kept Dalamud-free
|
|
// so the Build Suite pins every edge case.
|
|
// TEST-MIRROR: ../../../../Hellion Build test/Ui/CardClipPlanTests.cs
|
|
internal readonly record struct CardClipPlan(
|
|
int FirstVisible,
|
|
int LastVisible,
|
|
float LeadDummyHeight,
|
|
float EndDummyHeight
|
|
);
|
|
|
|
internal static class CardClipPlanner
|
|
{
|
|
// heights[i] is the cached height of row i in draw order. It carries no
|
|
// trailing ItemSpacing: every row ends inside DrawChunks, where spacing is
|
|
// pushed to zero, and ImGui writes the advance at item submission time.
|
|
// A row overlaps the viewport iff rowTop < windowBottom && rowBottom >
|
|
// windowTop. FirstVisible/LastVisible are -1 when nothing overlaps (empty
|
|
// list); callers then submit a single end dummy of the full content height
|
|
// so the scrollbar stays correct.
|
|
internal static CardClipPlan Plan(
|
|
IReadOnlyList<float> heights,
|
|
float scrollY,
|
|
float viewportHeight
|
|
)
|
|
{
|
|
var count = heights.Count;
|
|
if (count == 0)
|
|
return new CardClipPlan(-1, -1, 0f, 0f);
|
|
|
|
var windowTop = scrollY;
|
|
var windowBottom = scrollY + viewportHeight;
|
|
|
|
var first = -1;
|
|
var last = -1;
|
|
var leadDummy = 0f;
|
|
var endDummy = 0f;
|
|
|
|
var cursor = 0f; // running prefix sum = top edge of the current row
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
var rowTop = cursor;
|
|
var rowBottom = cursor + heights[i];
|
|
var overlaps = rowTop < windowBottom && rowBottom > windowTop;
|
|
|
|
if (overlaps)
|
|
{
|
|
if (first < 0)
|
|
first = i;
|
|
last = i;
|
|
}
|
|
else if (first < 0)
|
|
{
|
|
// Still above the visible window -> grows the lead dummy.
|
|
leadDummy += heights[i];
|
|
}
|
|
else
|
|
{
|
|
// Already past the visible window -> grows the end dummy.
|
|
endDummy += heights[i];
|
|
}
|
|
|
|
cursor = rowBottom;
|
|
}
|
|
|
|
return new CardClipPlan(first, last, leadDummy, endDummy);
|
|
}
|
|
}
|