换成不触发active的对象池队列模式
This commit is contained in:
@@ -234,28 +234,40 @@ namespace XericUI.XTable.Rendering.Component
|
||||
if (IsInSelectionRange != null && IsInSelectionRange(r, c))
|
||||
{
|
||||
var selImg = m_Assembler.GetImage("cell_multiselect");
|
||||
selImg.Rect.anchoredPosition = new Vector2(cellX, cellY);
|
||||
selImg.Rect.sizeDelta = new Vector2(cellW, cellH);
|
||||
selImg.Image.color = (r == selRow && c == selCol) ? focusColor : multiSelectColor;
|
||||
if (selImg != null)
|
||||
{
|
||||
selImg.Rect.anchoredPosition = new Vector2(cellX, cellY);
|
||||
selImg.Rect.sizeDelta = new Vector2(cellW, cellH);
|
||||
selImg.Image.color = (r == selRow && c == selCol) ? focusColor : multiSelectColor;
|
||||
}
|
||||
}
|
||||
else if (r == selRow && c == selCol)
|
||||
{
|
||||
var selImg = m_Assembler.GetImage("cell_select");
|
||||
selImg.Rect.anchoredPosition = new Vector2(cellX, cellY);
|
||||
selImg.Rect.sizeDelta = new Vector2(cellW, cellH);
|
||||
selImg.Image.color = selectionColor;
|
||||
if (selImg != null)
|
||||
{
|
||||
selImg.Rect.anchoredPosition = new Vector2(cellX, cellY);
|
||||
selImg.Rect.sizeDelta = new Vector2(cellW, cellH);
|
||||
selImg.Image.color = selectionColor;
|
||||
}
|
||||
}
|
||||
|
||||
// 网格线
|
||||
var hLine = m_Assembler.GetImage("cell_hline");
|
||||
hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH);
|
||||
hLine.Rect.sizeDelta = new Vector2(cellW, borderWidth);
|
||||
hLine.Image.color = borderColor;
|
||||
if (hLine != null)
|
||||
{
|
||||
hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH);
|
||||
hLine.Rect.sizeDelta = new Vector2(cellW, borderWidth);
|
||||
hLine.Image.color = borderColor;
|
||||
}
|
||||
|
||||
var vLine = m_Assembler.GetImage("cell_vline");
|
||||
vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - borderWidth, cellY);
|
||||
vLine.Rect.sizeDelta = new Vector2(borderWidth, cellH);
|
||||
vLine.Image.color = borderColor;
|
||||
if (vLine != null)
|
||||
{
|
||||
vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - borderWidth, cellY);
|
||||
vLine.Rect.sizeDelta = new Vector2(borderWidth, cellH);
|
||||
vLine.Image.color = borderColor;
|
||||
}
|
||||
|
||||
if (data == null) continue;
|
||||
|
||||
@@ -265,16 +277,19 @@ namespace XericUI.XTable.Rendering.Component
|
||||
if (!string.IsNullOrEmpty(data.Text))
|
||||
{
|
||||
var txt = m_Assembler.GetText("cell_text", cellNS);
|
||||
txt.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY);
|
||||
txt.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH);
|
||||
txt.Text.text = data.Text;
|
||||
txt.Text.color = GetStyleColor(cellNS, XericUIActionTable.STYLE_CELL_FG_COLOR,
|
||||
XericUIActionTable.FG_COLOR_FALLBACK);
|
||||
txt.Text.fontSize = GetStyleInt(cellNS, XericUIActionTable.STYLE_CELL_FONT_SIZE,
|
||||
XericUIActionTable.FONT_SIZE_FALLBACK);
|
||||
txt.Text.alignment = TextAlignmentOptions.Midline;
|
||||
txt.Text.font = GetStyleFontAsset?.Invoke(cellNS,
|
||||
XericUIActionTable.STYLE_CELL_FONT_ASSET) ?? txt.Text.font;
|
||||
if (txt != null)
|
||||
{
|
||||
txt.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY);
|
||||
txt.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH);
|
||||
txt.Text.SetText(data.Text);
|
||||
txt.Text.color = GetStyleColor(cellNS, XericUIActionTable.STYLE_CELL_FG_COLOR,
|
||||
XericUIActionTable.FG_COLOR_FALLBACK);
|
||||
txt.Text.fontSize = GetStyleInt(cellNS, XericUIActionTable.STYLE_CELL_FONT_SIZE,
|
||||
XericUIActionTable.FONT_SIZE_FALLBACK);
|
||||
txt.Text.alignment = TextAlignmentOptions.Midline;
|
||||
txt.Text.font = GetStyleFontAsset?.Invoke(cellNS,
|
||||
XericUIActionTable.STYLE_CELL_FONT_ASSET) ?? txt.Text.font;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CellContentType.Image:
|
||||
@@ -282,21 +297,27 @@ namespace XericUI.XTable.Rendering.Component
|
||||
{
|
||||
Sprite sprite = GetOrCreateSprite(data.Image);
|
||||
var img = m_Assembler.GetImage("cell_image", cellNS);
|
||||
img.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY);
|
||||
img.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH);
|
||||
img.Image.sprite = sprite;
|
||||
if (img != null)
|
||||
{
|
||||
img.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY);
|
||||
img.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH);
|
||||
img.Image.sprite = sprite;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CellContentType.Prefab:
|
||||
if (data.Prefab != null && PrefabPool != null)
|
||||
{
|
||||
GameObject instance = PrefabPool.Acquire(data.Prefab, r, c);
|
||||
RectTransform prt = instance.GetComponent<RectTransform>();
|
||||
prt.anchoredPosition = new Vector2(cellX, cellY);
|
||||
prt.sizeDelta = new Vector2(cellW, cellH);
|
||||
if (ActivePrefabMap != null)
|
||||
ActivePrefabMap[(r, c)] = instance;
|
||||
data.OnPrefabAcquire?.Invoke(instance);
|
||||
if (instance != null)
|
||||
{
|
||||
RectTransform prt = instance.GetComponent<RectTransform>();
|
||||
prt.anchoredPosition = new Vector2(cellX, cellY);
|
||||
prt.sizeDelta = new Vector2(cellW, cellH);
|
||||
if (ActivePrefabMap != null)
|
||||
ActivePrefabMap[(r, c)] = instance;
|
||||
data.OnPrefabAcquire?.Invoke(instance);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -340,27 +361,39 @@ namespace XericUI.XTable.Rendering.Component
|
||||
if (IsInSelectionRange != null && IsInSelectionRange(r, c))
|
||||
{
|
||||
var selImg = m_Assembler.GetImage("cell_multiselect");
|
||||
selImg.Rect.anchoredPosition = new Vector2(cellX, cellY);
|
||||
selImg.Rect.sizeDelta = new Vector2(cellW, cellH);
|
||||
selImg.Image.color = (r == selRow && c == selCol) ? rtFocusColor : rtMultiSelectColor;
|
||||
if (selImg != null)
|
||||
{
|
||||
selImg.Rect.anchoredPosition = new Vector2(cellX, cellY);
|
||||
selImg.Rect.sizeDelta = new Vector2(cellW, cellH);
|
||||
selImg.Image.color = (r == selRow && c == selCol) ? rtFocusColor : rtMultiSelectColor;
|
||||
}
|
||||
}
|
||||
else if (r == selRow && c == selCol)
|
||||
{
|
||||
var selImg = m_Assembler.GetImage("cell_select");
|
||||
selImg.Rect.anchoredPosition = new Vector2(cellX, cellY);
|
||||
selImg.Rect.sizeDelta = new Vector2(cellW, cellH);
|
||||
selImg.Image.color = rtSelectionColor;
|
||||
if (selImg != null)
|
||||
{
|
||||
selImg.Rect.anchoredPosition = new Vector2(cellX, cellY);
|
||||
selImg.Rect.sizeDelta = new Vector2(cellW, cellH);
|
||||
selImg.Image.color = rtSelectionColor;
|
||||
}
|
||||
}
|
||||
|
||||
var hLine = m_Assembler.GetImage("cell_hline");
|
||||
hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH);
|
||||
hLine.Rect.sizeDelta = new Vector2(cellW, Config.RuntimeBorderWidth);
|
||||
hLine.Image.color = Config.RuntimeBorderColor;
|
||||
if (hLine != null)
|
||||
{
|
||||
hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH);
|
||||
hLine.Rect.sizeDelta = new Vector2(cellW, Config.RuntimeBorderWidth);
|
||||
hLine.Image.color = Config.RuntimeBorderColor;
|
||||
}
|
||||
|
||||
var vLine = m_Assembler.GetImage("cell_vline");
|
||||
vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - Config.RuntimeBorderWidth, cellY);
|
||||
vLine.Rect.sizeDelta = new Vector2(Config.RuntimeBorderWidth, cellH);
|
||||
vLine.Image.color = Config.RuntimeBorderColor;
|
||||
if (vLine != null)
|
||||
{
|
||||
vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - Config.RuntimeBorderWidth, cellY);
|
||||
vLine.Rect.sizeDelta = new Vector2(Config.RuntimeBorderWidth, cellH);
|
||||
vLine.Image.color = Config.RuntimeBorderColor;
|
||||
}
|
||||
|
||||
if (data == null) continue;
|
||||
|
||||
@@ -370,9 +403,12 @@ namespace XericUI.XTable.Rendering.Component
|
||||
if (!string.IsNullOrEmpty(data.Text))
|
||||
{
|
||||
var txt = m_Assembler.GetText("cell_text", cellNS);
|
||||
txt.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY);
|
||||
txt.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH);
|
||||
txt.Text.text = data.Text;
|
||||
if (txt != null)
|
||||
{
|
||||
txt.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY);
|
||||
txt.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH);
|
||||
txt.Text.SetText(data.Text);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CellContentType.Image:
|
||||
@@ -380,21 +416,27 @@ namespace XericUI.XTable.Rendering.Component
|
||||
{
|
||||
Sprite sprite = GetOrCreateSprite(data.Image);
|
||||
var img = m_Assembler.GetImage("cell_image", cellNS);
|
||||
img.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY);
|
||||
img.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH);
|
||||
img.Image.sprite = sprite;
|
||||
if (img != null)
|
||||
{
|
||||
img.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY);
|
||||
img.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH);
|
||||
img.Image.sprite = sprite;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CellContentType.Prefab:
|
||||
if (data.Prefab != null && PrefabPool != null)
|
||||
{
|
||||
GameObject instance = PrefabPool.Acquire(data.Prefab, r, c);
|
||||
RectTransform prt = instance.GetComponent<RectTransform>();
|
||||
prt.anchoredPosition = new Vector2(cellX, cellY);
|
||||
prt.sizeDelta = new Vector2(cellW, cellH);
|
||||
if (ActivePrefabMap != null)
|
||||
ActivePrefabMap[(r, c)] = instance;
|
||||
data.OnPrefabAcquire?.Invoke(instance);
|
||||
if (instance != null)
|
||||
{
|
||||
RectTransform prt = instance.GetComponent<RectTransform>();
|
||||
prt.anchoredPosition = new Vector2(cellX, cellY);
|
||||
prt.sizeDelta = new Vector2(cellW, cellH);
|
||||
if (ActivePrefabMap != null)
|
||||
ActivePrefabMap[(r, c)] = instance;
|
||||
data.OnPrefabAcquire?.Invoke(instance);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -195,6 +195,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
|
||||
string key = inRange ? "cell_multiselect" : "cell_select";
|
||||
var img = m_Assembler.GetImage(key, cellNS);
|
||||
if (img == null) return;
|
||||
img.Rect.anchoredPosition = new Vector2(cellX, cellY);
|
||||
img.Rect.sizeDelta = new Vector2(cellW, cellH);
|
||||
|
||||
@@ -240,17 +241,23 @@ namespace XericUI.XTable.Rendering.Component
|
||||
|
||||
// 水平网格线(底部)
|
||||
var hLine = m_Assembler.GetImage("cell_hline", cellNS);
|
||||
hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH);
|
||||
hLine.Rect.sizeDelta = new Vector2(cellW, borderWidth);
|
||||
hLine.Image.color = borderColor;
|
||||
objs.HLine = hLine;
|
||||
if (hLine != null)
|
||||
{
|
||||
hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH);
|
||||
hLine.Rect.sizeDelta = new Vector2(cellW, borderWidth);
|
||||
hLine.Image.color = borderColor;
|
||||
objs.HLine = hLine;
|
||||
}
|
||||
|
||||
// 垂直网格线(右侧)
|
||||
var vLine = m_Assembler.GetImage("cell_vline", cellNS);
|
||||
vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - borderWidth, cellY);
|
||||
vLine.Rect.sizeDelta = new Vector2(borderWidth, cellH);
|
||||
vLine.Image.color = borderColor;
|
||||
objs.VLine = vLine;
|
||||
if (vLine != null)
|
||||
{
|
||||
vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - borderWidth, cellY);
|
||||
vLine.Rect.sizeDelta = new Vector2(borderWidth, cellH);
|
||||
vLine.Image.color = borderColor;
|
||||
objs.VLine = vLine;
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderCellText(XTableCellData data,
|
||||
@@ -260,9 +267,10 @@ namespace XericUI.XTable.Rendering.Component
|
||||
if (string.IsNullOrEmpty(data.Text)) return;
|
||||
|
||||
var txt = m_Assembler.GetText("cell_text", cellNS);
|
||||
if (txt == null) return;
|
||||
txt.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY);
|
||||
txt.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH);
|
||||
txt.Text.text = data.Text;
|
||||
txt.Text.SetText(data.Text);
|
||||
|
||||
if (editorMode)
|
||||
{
|
||||
@@ -283,6 +291,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
|
||||
Sprite sprite = GetOrCreateSprite(data.Image);
|
||||
var img = m_Assembler.GetImage("cell_image", cellNS);
|
||||
if (img == null) return;
|
||||
img.Rect.anchoredPosition = new Vector2(cellX + CellPadding, cellY);
|
||||
img.Rect.sizeDelta = new Vector2(cellW - CellPadding2, cellH);
|
||||
img.Image.sprite = sprite;
|
||||
@@ -296,6 +305,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
if (data.Prefab == null) return;
|
||||
|
||||
GameObject instance = m_PrefabPool.Acquire(data.Prefab, row, col);
|
||||
if (instance == null) return;
|
||||
RectTransform prt = instance.GetComponent<RectTransform>();
|
||||
prt.anchoredPosition = new Vector2(cellX, cellY);
|
||||
prt.sizeDelta = new Vector2(cellW, cellH);
|
||||
@@ -471,16 +481,14 @@ namespace XericUI.XTable.Rendering.Component
|
||||
|
||||
private void CleanOrphanChildren()
|
||||
{
|
||||
Transform poolRoot = m_Assembler?.PoolRoot;
|
||||
Transform prefabPoolRoot = m_PrefabPool?.PoolRoot;
|
||||
Transform contentT = ContentTransform;
|
||||
Transform borderT = contentT?.Find("_TableBorders");
|
||||
|
||||
for (int i = contentT.childCount - 1; i >= 0; i--)
|
||||
{
|
||||
var child = contentT.GetChild(i);
|
||||
if (poolRoot != null && child == poolRoot) continue;
|
||||
if (prefabPoolRoot != null && child == prefabPoolRoot) continue;
|
||||
// 跳过池管理的对象(标记有 POOL_FLAGS = DontSave | HideInHierarchy)
|
||||
if ((child.hideFlags & HideFlags.DontSave) != 0) continue;
|
||||
if (m_BackgroundGo != null && child.gameObject == m_BackgroundGo) continue;
|
||||
if (borderT != null && child == borderT) continue;
|
||||
|
||||
|
||||
@@ -37,10 +37,6 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
#region 字段
|
||||
|
||||
private Transform m_Parent;
|
||||
private Transform m_PoolRoot;
|
||||
|
||||
/// <summary>池根节点(所有回收对象均挂在此节点下,节点本身处于 inactive)</summary>
|
||||
public Transform PoolRoot => m_PoolRoot;
|
||||
|
||||
/// <summary>运行时的默认样式命名空间(编辑器下为 null,不绑定)</summary>
|
||||
private string m_DefaultStyleNamespace;
|
||||
@@ -48,14 +44,20 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
/// <summary>所有已绑定的 StyleBoundElement 回调集合(用于样式变更时通知外部)</summary>
|
||||
public event System.Action OnStyleChangeDetected;
|
||||
|
||||
private Stack<PooledImage> m_ImagePool = new Stack<PooledImage>();
|
||||
private Stack<PooledText> m_TextPool = new Stack<PooledText>();
|
||||
private Queue<PooledImage> m_ImagePool = new Queue<PooledImage>();
|
||||
private Queue<PooledText> m_TextPool = new Queue<PooledText>();
|
||||
private List<PooledImage> m_ActiveImages = new List<PooledImage>();
|
||||
private List<PooledText> m_ActiveTexts = new List<PooledText>();
|
||||
|
||||
/// <summary>HideFlags 应用于所有动态创建的对象(不保存、不在 Hierarchy 显示)</summary>
|
||||
private const HideFlags POOL_FLAGS = HideFlags.DontSave | HideFlags.HideInHierarchy;
|
||||
|
||||
/// <summary>渲染项目总数上限,超出后 GetImage/GetText 返回 null 并发出警告</summary>
|
||||
private const int MAX_POOL_ITEMS = 256;
|
||||
|
||||
private int m_ImageCreatedCount;
|
||||
private int m_TextCreatedCount;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 构造函数与析构
|
||||
@@ -64,12 +66,6 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
{
|
||||
m_Parent = parent;
|
||||
m_DefaultStyleNamespace = defaultStyleNamespace;
|
||||
|
||||
GameObject poolRoot = new GameObject("_CellPool");
|
||||
poolRoot.hideFlags = POOL_FLAGS;
|
||||
poolRoot.transform.SetParent(parent, false);
|
||||
poolRoot.SetActive(false);
|
||||
m_PoolRoot = poolRoot.transform;
|
||||
}
|
||||
|
||||
/// <summary>彻底销毁所有池对象(包括活跃和休眠的)</summary>
|
||||
@@ -91,18 +87,11 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
// 杀死池中对象
|
||||
while (m_ImagePool.Count > 0)
|
||||
{
|
||||
KillObject(m_ImagePool.Pop().Root);
|
||||
KillObject(m_ImagePool.Dequeue().Root);
|
||||
}
|
||||
while (m_TextPool.Count > 0)
|
||||
{
|
||||
KillObject(m_TextPool.Pop().Root);
|
||||
}
|
||||
|
||||
// 杀死池根
|
||||
if (m_PoolRoot != null)
|
||||
{
|
||||
KillObject(m_PoolRoot.gameObject);
|
||||
m_PoolRoot = null;
|
||||
KillObject(m_TextPool.Dequeue().Root);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,14 +121,18 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
PooledImage item;
|
||||
if (m_ImagePool.Count > 0)
|
||||
{
|
||||
item = m_ImagePool.Pop();
|
||||
item.Root.SetActive(true);
|
||||
item.Root.transform.SetParent(m_Parent, false);
|
||||
item = m_ImagePool.Dequeue();
|
||||
ResetImageDefaults(item);
|
||||
}
|
||||
else if (m_ImageCreatedCount < MAX_POOL_ITEMS)
|
||||
{
|
||||
item = CreateImage(name);
|
||||
m_ImageCreatedCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
item = CreateImage(name);
|
||||
Debug.LogWarning($"[XericUIActionTable] Image 池已达上限 {MAX_POOL_ITEMS},无法分配新对象");
|
||||
return null;
|
||||
}
|
||||
BindStyle(item.Style, styleNamespace);
|
||||
m_ActiveImages.Add(item);
|
||||
@@ -151,14 +144,18 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
PooledText item;
|
||||
if (m_TextPool.Count > 0)
|
||||
{
|
||||
item = m_TextPool.Pop();
|
||||
item.Root.SetActive(true);
|
||||
item.Root.transform.SetParent(m_Parent, false);
|
||||
item = m_TextPool.Dequeue();
|
||||
ResetTextDefaults(item);
|
||||
}
|
||||
else if (m_TextCreatedCount < MAX_POOL_ITEMS)
|
||||
{
|
||||
item = CreateText(name);
|
||||
m_TextCreatedCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
item = CreateText(name);
|
||||
Debug.LogWarning($"[XericUIActionTable] Text 池已达上限 {MAX_POOL_ITEMS},无法分配新对象");
|
||||
return null;
|
||||
}
|
||||
BindStyle(item.Style, styleNamespace);
|
||||
m_ActiveTexts.Add(item);
|
||||
@@ -214,18 +211,13 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
private void ReturnImage(PooledImage item)
|
||||
{
|
||||
item.Style?.Unbind();
|
||||
item.Root.SetActive(false);
|
||||
item.Root.transform.SetParent(m_PoolRoot, false);
|
||||
m_ImagePool.Push(item);
|
||||
m_ImagePool.Enqueue(item);
|
||||
}
|
||||
|
||||
private void ReturnText(PooledText item)
|
||||
{
|
||||
item.Style?.Unbind();
|
||||
item.Text.text = "";
|
||||
item.Root.SetActive(false);
|
||||
item.Root.transform.SetParent(m_PoolRoot, false);
|
||||
m_TextPool.Push(item);
|
||||
m_TextPool.Enqueue(item);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -251,7 +243,7 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
item.Rect.pivot = PIVOT_TOPLEFT;
|
||||
item.Rect.anchoredPosition = Vector2.zero;
|
||||
item.Rect.sizeDelta = Vector2.zero;
|
||||
item.Text.text = "";
|
||||
item.Text.SetText(string.Empty);
|
||||
item.Text.color = Color.black;
|
||||
item.Text.fontSize = 14;
|
||||
item.Text.alignment = TextAlignmentOptions.Midline;
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Pool;
|
||||
|
||||
namespace XericUI.XTable.Rendering.Elements
|
||||
{
|
||||
/// <summary>
|
||||
/// 预制体对象池——按原型分组管理,每个预制体对应一个独立的对象池。
|
||||
/// 使用 Stack + HashSet 模式与 <see cref="CellAssembler"/> 保持一致。
|
||||
/// 使用 Queue + HashSet 模式,FIFO 保证对象按回收顺序均匀复用。
|
||||
/// </summary>
|
||||
public class PrefabPrototypePool
|
||||
{
|
||||
@@ -16,8 +15,8 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
private class PrefabPool
|
||||
{
|
||||
public GameObject Prototype;
|
||||
/// <summary>休眠实例栈(池满时先归还的优先复用)</summary>
|
||||
public Stack<GameObject> Available = new Stack<GameObject>();
|
||||
/// <summary>休眠实例队列(FIFO,先归还的优先复用)</summary>
|
||||
public Queue<GameObject> Available = new Queue<GameObject>();
|
||||
/// <summary>活跃实例集合(O(1) 查找 + 防止重复归还)</summary>
|
||||
public HashSet<GameObject> Active = new HashSet<GameObject>();
|
||||
}
|
||||
@@ -28,10 +27,10 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
|
||||
private Dictionary<GameObject, PrefabPool> m_Pools = new Dictionary<GameObject, PrefabPool>();
|
||||
private Transform m_Parent;
|
||||
private Transform m_PoolRoot;
|
||||
|
||||
/// <summary>池根节点(所有回收对象均挂在此节点下,节点本身处于 inactive)</summary>
|
||||
public Transform PoolRoot => m_PoolRoot;
|
||||
/// <summary>渲染项目总数上限</summary>
|
||||
private const int MAX_PREFAB_ITEMS = 256;
|
||||
private int m_TotalCreated;
|
||||
|
||||
private const HideFlags POOL_FLAGS = HideFlags.DontSave | HideFlags.HideInHierarchy;
|
||||
|
||||
@@ -45,15 +44,9 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
public PrefabPrototypePool(Transform parent)
|
||||
{
|
||||
m_Parent = parent;
|
||||
|
||||
GameObject poolRoot = new GameObject("_PrefabPoolRoot");
|
||||
poolRoot.hideFlags = POOL_FLAGS;
|
||||
poolRoot.transform.SetParent(parent, false);
|
||||
poolRoot.SetActive(false);
|
||||
m_PoolRoot = poolRoot.transform;
|
||||
}
|
||||
|
||||
/// <summary>彻底销毁所有池对象(活跃 + 休眠 + 池根)</summary>
|
||||
/// <summary>彻底销毁所有池对象(活跃 + 休眠)</summary>
|
||||
public void DestroyAll()
|
||||
{
|
||||
foreach (var kv in m_Pools)
|
||||
@@ -65,15 +58,9 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
pool.Active.Clear();
|
||||
// 销毁休眠实例
|
||||
while (pool.Available.Count > 0)
|
||||
KillObject(pool.Available.Pop());
|
||||
KillObject(pool.Available.Dequeue());
|
||||
}
|
||||
m_Pools.Clear();
|
||||
|
||||
if (m_PoolRoot != null)
|
||||
{
|
||||
KillObject(m_PoolRoot.gameObject);
|
||||
m_PoolRoot = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void KillObject(GameObject go)
|
||||
@@ -89,7 +76,7 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
|
||||
#region 池操作
|
||||
|
||||
/// <summary>从池中获取实例(池空则 Instantiate 新的)</summary>
|
||||
/// <summary>从池中获取实例(FIFO 复用;池空且未达上限则 Instantiate;已达上限返回 null)</summary>
|
||||
public GameObject Acquire(GameObject prefab, int row, int col)
|
||||
{
|
||||
if (prefab == null) return null;
|
||||
@@ -99,14 +86,18 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
GameObject instance;
|
||||
if (pool.Available.Count > 0)
|
||||
{
|
||||
instance = pool.Available.Pop();
|
||||
instance.SetActive(true);
|
||||
instance.transform.SetParent(m_Parent, false);
|
||||
instance = pool.Available.Dequeue();
|
||||
}
|
||||
else
|
||||
else if (m_TotalCreated < MAX_PREFAB_ITEMS)
|
||||
{
|
||||
instance = Object.Instantiate(prefab, m_Parent);
|
||||
instance.hideFlags = POOL_FLAGS;
|
||||
m_TotalCreated++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"[XericUIActionTable] Prefab 池已达上限 {MAX_PREFAB_ITEMS},无法分配新实例");
|
||||
return null;
|
||||
}
|
||||
|
||||
instance.name = $"_prefab_{row}_{col}";
|
||||
@@ -122,7 +113,7 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>将指定实例归还对象池(Deactivate + 移入 PoolRoot)</summary>
|
||||
/// <summary>将指定实例归还对象池(不入池根,原地保留避免 OnEnable/OnDisable)</summary>
|
||||
public void Release(GameObject instance)
|
||||
{
|
||||
if (instance == null) return;
|
||||
@@ -132,9 +123,7 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
{
|
||||
if (kv.Value.Active.Remove(instance))
|
||||
{
|
||||
instance.SetActive(false);
|
||||
instance.transform.SetParent(m_PoolRoot, false);
|
||||
kv.Value.Available.Push(instance);
|
||||
kv.Value.Available.Enqueue(instance);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -143,7 +132,7 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
KillObject(instance);
|
||||
}
|
||||
|
||||
/// <summary>将所有活跃实例回收至池</summary>
|
||||
/// <summary>将所有活跃实例回收至池(原地保留,仅从活跃集移除并入队)</summary>
|
||||
public void ReturnAll()
|
||||
{
|
||||
foreach (var kv in m_Pools)
|
||||
@@ -151,9 +140,7 @@ namespace XericUI.XTable.Rendering.Elements
|
||||
var pool = kv.Value;
|
||||
foreach (var go in pool.Active)
|
||||
{
|
||||
go.SetActive(false);
|
||||
go.transform.SetParent(m_PoolRoot, false);
|
||||
pool.Available.Push(go);
|
||||
pool.Available.Enqueue(go);
|
||||
}
|
||||
pool.Active.Clear();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user