Merge pull request #1 from Seeker1437/experiement/wrapping-node-list
Experimental - Row Pooling
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user