Merge pull request #1 from Seeker1437/experiement/wrapping-node-list

Experimental - Row Pooling
This commit is contained in:
Jeffrey Veenhuis
2025-12-20 11:17:39 +01:00
committed by GitHub
+97 -32
View File
@@ -1,72 +1,137 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices;
using KamiToolKit; using KamiToolKit;
using KamiToolKit. Nodes; using KamiToolKit. Nodes;
namespace AetherBags.Nodes namespace AetherBags.Nodes
{ {
public class WrappingGridNode<T> : LayoutListNode where T : NodeBase public sealed class WrappingGridNode<T> : LayoutListNode where T : NodeBase
{ {
public float HorizontalSpacing { get; set; } = 10;
public float VerticalSpacing { get; set; } = 10;
private List<List<NodeBase>> _rows = new(); public float HorizontalSpacing { get; set; } = 10f;
public float VerticalSpacing { get; set; } = 10f;
private readonly List<List<NodeBase>> _rows = new();
private readonly Stack<List<NodeBase>> _rowPool = new();
private float _requiredHeight;
private bool _requiredHeightDirty = true;
protected override void InternalRecalculateLayout() protected override void InternalRecalculateLayout()
{ {
if (NodeList. Count == 0) RecycleAllRows();
return;
_rows.Clear(); int count = NodeList.Count;
if (count == 0)
{
_requiredHeight = 0f;
_requiredHeightDirty = false;
return;
}
float availableWidth = Width; float availableWidth = Width;
float currentX = 0f; float hSpace = HorizontalSpacing;
float vSpace = VerticalSpacing;
float startX = FirstItemSpacing;
float currentX = startX;
float currentY = 0f; float currentY = 0f;
float rowHeight = 0f; float rowHeight = 0f;
List<NodeBase> currentRow = new();
foreach (var node in NodeList) List<NodeBase> currentRow = RentRowList(capacityHint: 8);
for (int i = 0; i < count; i++)
{ {
float nodeWidth = node.Width; NodeBase node = NodeList[i];
float nodeHeight = node.Height;
if (currentX + nodeWidth > availableWidth && currentRow.Count > 0) float nodeWidth = node.Width;
if (currentRow.Count != 0 && (currentX + nodeWidth) > availableWidth)
{ {
_rows.Add(currentRow); _rows.Add(currentRow);
currentRow = new();
currentY += rowHeight + VerticalSpacing; currentY += rowHeight + vSpace;
currentX = 0f; currentX = startX;
rowHeight = 0f; rowHeight = 0f;
currentRow = RentRowList(capacityHint: 8);
} }
node.X = currentX; node.X = currentX;
node. Y = currentY; node.Y = currentY;
AdjustNode(node); AdjustNode(node);
currentX += nodeWidth + HorizontalSpacing; float nodeHeight = node.Height;
rowHeight = Math.Max(rowHeight, nodeHeight); if (nodeHeight > rowHeight) rowHeight = nodeHeight;
currentRow.Add(node); currentRow.Add(node);
currentX += nodeWidth + hSpace;
} }
if (currentRow.Count > 0) if (currentRow.Count != 0)
{ {
_rows.Add(currentRow); _rows.Add(currentRow);
} }
} else
public float GetRequiredHeight()
{
if (NodeList.Count == 0)
return 0f;
float maxY = 0f;
foreach (var node in NodeList)
{ {
float nodeBottom = node.Y + node.Height; RecycleRow(currentRow);
maxY = Math. Max(maxY, nodeBottom);
} }
return maxY; _requiredHeightDirty = true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float GetRequiredHeight()
{
if (!_requiredHeightDirty) return _requiredHeight;
float maxBottom = 0f;
int count = NodeList.Count;
for (int i = 0; i < count; i++)
{
NodeBase node = NodeList[i];
float bottom = node.Y + node.Height;
if (bottom > maxBottom) maxBottom = bottom;
}
_requiredHeight = maxBottom;
_requiredHeightDirty = false;
return maxBottom;
}
private void RecycleAllRows()
{
for (int i = 0; i < _rows.Count; i++)
{
List<NodeBase> row = _rows[i];
row.Clear();
_rowPool.Push(row);
}
_rows.Clear();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private List<NodeBase> RentRowList(int capacityHint)
{
if (_rowPool.Count != 0)
{
List<NodeBase> row = _rowPool.Pop();
if (row.Capacity < capacityHint) row.Capacity = capacityHint;
return row;
}
return new List<NodeBase>(capacityHint);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void RecycleRow(List<NodeBase> row)
{
row.Clear();
_rowPool.Push(row);
} }
} }
} }