using UnityEngine;
namespace XericUI.XTable.Rendering
{
///
/// 左上角坐标系的视图矩形。
/// Unity 的 Rect 是左下角原点(Y-up),表格数据索引是左上角原点(Y-down)。
/// 此类负责坐标转换和可见单元格范围计算。
///
public struct XTableViewRect
{
/// 左上角 X 坐标
public float X;
/// 左上角 Y 坐标(从上到下递增)
public float Y;
/// 视图宽度
public float Width;
/// 视图高度
public float Height;
/// 右边界
public float XMax => X + Width;
/// 下边界
public float YMax => Y + Height;
///
/// 从 Unity Rect(左下角原点)转换为 TableViewRect(左上角原点)
///
/// Unity 坐标系下的矩形
/// 容器总高度(用于 Y 轴翻转)
public static XTableViewRect FromUnityRect(Rect unityRect, float containerHeight)
{
return new XTableViewRect
{
X = unityRect.xMin,
Y = containerHeight - unityRect.yMax,
Width = unityRect.width,
Height = unityRect.height
};
}
///
/// 转换为 Unity Rect(左下角原点)
///
public Rect ToUnityRect(float containerHeight)
{
return new Rect(X, containerHeight - Y - Height, Width, Height);
}
///
/// 通过行列尺寸计算可见单元格范围。
/// 累加行高/列宽直到超出视图范围。
///
/// 每行高度数组
/// 每列宽度数组
/// 可见起始行(包含)
/// 可见结束行(不包含)
/// 可见起始列(包含)
/// 可见结束列(不包含)
public void GetVisibleCellRange(
float[] rowHeights, float[] colWidths,
out int startRow, out int endRow,
out int startCol, out int endCol)
{
startRow = 0;
endRow = 0;
startCol = 0;
endCol = 0;
if (rowHeights == null || colWidths == null) return;
// 计算行范围(Y 方向,从上到下)
float accumulatedY = 0f;
for (int r = 0; r < rowHeights.Length; r++)
{
float rowBottom = accumulatedY + rowHeights[r];
if (rowBottom > Y && accumulatedY < YMax)
{
if (startRow == 0 && accumulatedY < YMax)
startRow = r;
endRow = r + 1;
}
accumulatedY = rowBottom;
if (accumulatedY > YMax) break;
}
// 计算列范围(X 方向,从左到右)
float accumulatedX = 0f;
for (int c = 0; c < colWidths.Length; c++)
{
float colRight = accumulatedX + colWidths[c];
if (colRight > X && accumulatedX < XMax)
{
if (startCol == 0 && accumulatedX < XMax)
startCol = c;
endCol = c + 1;
}
accumulatedX = colRight;
if (accumulatedX > XMax) break;
}
}
}
}