Files
XericUIActionVessel/Runtime/XTable/Rendering/Component/XericUIActionTable.Data.cs
T

195 lines
6.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using UnityEngine;
using XericUI.Core.Base;
using XericUI.XTable.Core;
namespace XericUI.XTable.Rendering.Component
{
/// <summary>
/// 表格数据与坐标计算——可见性判定、坐标公式、尺寸重算、四叉树维护。
/// </summary>
public partial class XericUIActionTable
{
#region 可见性判定
/// <summary>判断指定单元格是否与当前可见矩形有重叠(用于裁剪剔除)</summary>
private bool IsCellVisible(int row, int col)
{
// 计入 m_ContentOffset 以匹配单元格在 Content 中的实际渲染位置
float cellLeft = GetColLeftX(col) + m_ContentOffset;
float cellRight = cellLeft + m_ColWidths[col];
float cellTop = GetRowTopY(row) + m_ContentOffset;
float cellBottom = cellTop + m_RowHeights[row];
return cellRight > m_VisibleRect.x && cellLeft < m_VisibleRect.xMax &&
cellBottom > m_VisibleRect.y && cellTop < m_VisibleRect.yMax;
}
#endregion
#region 坐标公式
private float GetRowTopY(int row)
{
float y = 0;
for (int i = 0; i < row && i < m_RowHeights.Length; i++)
y += m_RowHeights[i];
return y;
}
private float GetColLeftX(int col)
{
float x = 0;
for (int i = 0; i < col && i < m_ColWidths.Length; i++)
x += m_ColWidths[i];
return x;
}
#endregion
#region Sprite 缓存
/// <summary>将 Texture2D 转为 Sprite(带缓存),用于 Image 类型单元格渲染</summary>
private Sprite GetOrCreateSprite(Texture2D texture)
{
if (texture == null) return null;
if (m_SpriteCache == null)
m_SpriteCache = new Dictionary<Texture2D, Sprite>();
if (!m_SpriteCache.TryGetValue(texture, out Sprite sprite))
{
sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
m_SpriteCache[texture] = sprite;
}
return sprite;
}
#endregion
#region 尺寸计算与可见矩形
private void RecalculateTotalSize()
{
m_TotalWidth = 0;
if (m_ColWidths != null)
foreach (float w in m_ColWidths)
m_TotalWidth += w;
m_TotalHeight = 0;
if (m_RowHeights != null)
foreach (float h in m_RowHeights)
m_TotalHeight += h;
m_ContentOffset = GetCellBorderWidth(m_DefaultStyleNamespace) * 0.5f;
float pad = m_ContentOffset * 2f;
if (m_ScrollRect != null && m_ScrollRect.content != null)
m_ScrollRect.content.sizeDelta = new Vector2(
m_TotalWidth + pad, m_TotalHeight + pad);
}
private void UpdateVisibleRect()
{
m_VisibleRect = new Rect(0, 0, m_TotalWidth, m_TotalHeight);
if (m_ScrollRect == null || m_ScrollRect.viewport == null || m_ScrollRect.content == null)
return;
RectTransform vt = m_ScrollRect.viewport;
RectTransform ct = m_ScrollRect.content as RectTransform;
if (vt == null || ct == null) return;
// Content 的 anchor/pivot 在 Awake 中强制设为 (0,1),anchoredPosition
// 直接表示 Content 左上角相对于 Viewport 左上角的偏移。
Vector2 ap = ct.anchoredPosition;
float visibleLeft = -ap.x;
float visibleTop = -ap.y;
m_VisibleRect = new Rect(visibleLeft, visibleTop, vt.rect.width, vt.rect.height);
}
private void CalcVisibleRange(out int sr, out int er, out int sc, out int ec)
{
sr = 0;
er = 0;
sc = 0;
ec = 0;
float accY = 0;
for (int r = 0; r < m_RowHeights.Length; r++)
{
float rowBottom = accY + m_RowHeights[r];
if (rowBottom > m_VisibleRect.y && accY < m_VisibleRect.yMax)
{
if (er == 0 && sr == 0) sr = r;
er = r + 1;
}
accY = rowBottom;
if (accY > m_VisibleRect.yMax) break;
}
float accX = 0;
for (int c = 0; c < m_ColWidths.Length; c++)
{
float colRight = accX + m_ColWidths[c];
if (colRight > m_VisibleRect.x && accX < m_VisibleRect.xMax)
{
if (ec == 0 && sc == 0) sc = c;
ec = c + 1;
}
accX = colRight;
if (accX > m_VisibleRect.xMax) break;
}
if (sr < 0) sr = 0;
if (sc < 0) sc = 0;
}
#endregion
#region 四叉树
/// <summary>强制重建四叉树(外部调用入口,适合编辑器调试或手动刷新)</summary>
public void ForceRebuildQuadtree()
{
if (m_Quadtree == null)
m_Quadtree = new XTableQuadtree();
MaintainQuadtree();
}
/// <summary>从当前 XTableData 收集单元格信息并重建四叉树</summary>
private void MaintainQuadtree()
{
if (m_TableData == null || m_RowHeights == null || m_ColWidths == null)
return;
if (m_Quadtree == null)
m_Quadtree = new XTableQuadtree();
// 收集所有有数据的单元格(跳过被合并覆盖的子单元格)
var cells = new List<XTableQuadtreeCell>();
for (int r = 0; r < m_RowHeights.Length; r++)
{
for (int c = 0; c < m_ColWidths.Length; c++)
{
if (m_TableData.IsCellMerged(r, c)) continue;
var data = m_TableData.GetCell(r, c);
if (data == null) continue;
string ns = !string.IsNullOrEmpty(data.StyleNamespace)
? data.StyleNamespace : m_DefaultStyleNamespace;
cells.Add(new XTableQuadtreeCell { Row = r, Col = c, Namespace = ns });
}
}
m_Quadtree.Build(m_TotalWidth, m_TotalHeight, m_RowHeights, m_ColWidths, cells, Config.QuadtreeMaxCellsPerNode);
}
#endregion
}
}