单元格内添加样式属性字段,以及内容类型切换的功能。
This commit is contained in:
@@ -2,6 +2,7 @@ using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XericLibrary.Runtime.MacroLibrary;
|
||||
using XericLibrary.Runtime.SuperStyleSheet;
|
||||
using XericUI.XTable.Core;
|
||||
using XericUI.XTable.Rendering.Component;
|
||||
|
||||
@@ -177,9 +178,9 @@ namespace XericUIEditor.XTable
|
||||
if (GUILayout.Button("手动刷新视图", GUILayout.Height(22)))
|
||||
EditorApplication.delayCall += () => m_Table.RefreshView();
|
||||
|
||||
// ── 预制体配置 ──
|
||||
// ── 单元格配置 ──
|
||||
EditorGUILayout.Space(4);
|
||||
EditorGUILayout.LabelField("单元格预制体配置", EditorStyles.boldLabel);
|
||||
EditorGUILayout.LabelField("单元格配置", EditorStyles.boldLabel);
|
||||
int selRow = m_Table.SelectedRow;
|
||||
int selCol = m_Table.SelectedCol;
|
||||
if (selRow < 0 || selCol < 0)
|
||||
@@ -189,30 +190,79 @@ namespace XericUIEditor.XTable
|
||||
else
|
||||
{
|
||||
var data = m_Table.TableData?.GetCell(selRow, selCol);
|
||||
GameObject currentPrefab = data?.Prefab;
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.TextField("目标单元格", $"({selRow}, {selCol})");
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
GameObject newPrefab = (GameObject)EditorGUILayout.ObjectField(
|
||||
"预制体", currentPrefab, typeof(GameObject), false);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("应用预制体", GUILayout.Height(22)))
|
||||
if (data == null)
|
||||
{
|
||||
Undo.RecordObject(m_Table, "Set Cell Prefab");
|
||||
m_Table.SetCellPrefab(selRow, selCol, newPrefab);
|
||||
EditorUtility.SetDirty(m_Table);
|
||||
Repaint();
|
||||
EditorGUILayout.HelpBox("单元格数据为空", MessageType.Warning);
|
||||
}
|
||||
if (GUILayout.Button("清除预制体", GUILayout.Height(22)))
|
||||
else
|
||||
{
|
||||
Undo.RecordObject(m_Table, "Clear Cell Prefab");
|
||||
m_Table.ClearCellPrefab(selRow, selCol);
|
||||
EditorUtility.SetDirty(m_Table);
|
||||
Repaint();
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.TextField("目标单元格", $"({selRow}, {selCol})");
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
// 内容类型
|
||||
CellContentType ct = (CellContentType)EditorGUILayout.EnumPopup("内容类型", data.ContentType);
|
||||
|
||||
// 根据类型显示对应字段
|
||||
switch (ct)
|
||||
{
|
||||
case CellContentType.Text:
|
||||
EditorGUILayout.LabelField("文本内容", data.Text ?? "(空)");
|
||||
break;
|
||||
case CellContentType.Image:
|
||||
EditorGUILayout.ObjectField("图片纹理", data.Image, typeof(Texture2D), false);
|
||||
break;
|
||||
case CellContentType.Prefab:
|
||||
GameObject newPrefab = (GameObject)EditorGUILayout.ObjectField(
|
||||
"预制体", data.Prefab, typeof(GameObject), false);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RecordObject(m_Table, "Set Cell Prefab");
|
||||
data.Prefab = newPrefab;
|
||||
data.ContentType = ct;
|
||||
m_Table.SetCellPrefab(selRow, selCol, newPrefab);
|
||||
EditorUtility.SetDirty(m_Table);
|
||||
Repaint();
|
||||
}
|
||||
goto skipEndChangeCheck;
|
||||
}
|
||||
// 默认 Text 类型
|
||||
string newText = EditorGUILayout.TextField("文本内容", data.Text ?? "");
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RecordObject(m_Table, "Edit Cell");
|
||||
data.Text = newText;
|
||||
data.ContentType = ct;
|
||||
EditorUtility.SetDirty(m_Table);
|
||||
m_Table.MarkDirty(TableDirtyType.DataChanged);
|
||||
EditorUtility.SetDirty(m_Table);
|
||||
Repaint();
|
||||
}
|
||||
skipEndChangeCheck:
|
||||
;
|
||||
|
||||
// 样式
|
||||
EditorGUILayout.Space(2);
|
||||
EditorGUILayout.LabelField("单元格样式 (StyleMember)", EditorStyles.miniBoldLabel);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
string ns = EditorGUILayout.TextField("命名空间",
|
||||
data.CellStyle?.CurrentNamespace ?? "");
|
||||
string path = EditorGUILayout.TextField("样式路径",
|
||||
data.CellStyle?.StylePath ?? "");
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RecordObject(m_Table, "Edit Cell Style");
|
||||
if (data.CellStyle == null)
|
||||
data.CellStyle = new StyleMember();
|
||||
data.CellStyle.CurrentNamespace = ns;
|
||||
data.CellStyle.StylePath = path;
|
||||
EditorUtility.SetDirty(m_Table);
|
||||
m_Table.MarkDirty(TableDirtyType.DataChanged);
|
||||
Repaint();
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
@@ -1,53 +1,84 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using XericLibrary.Runtime.SuperStyleSheet;
|
||||
|
||||
namespace XericUI.XTable.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// 单元格数据模型——仅保存数据内容,不保存自身尺寸。
|
||||
/// 尺寸由渲染阶段的行列标题(行高/列宽)决定。
|
||||
/// 样式通过 StyleNamespace 字符串引用 StyleManager 中的命名空间。
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class XTableCellData
|
||||
{
|
||||
/// <summary>文本内容</summary>
|
||||
public string Text;
|
||||
/// <summary>单元格内容类型——决定渲染时使用哪种内容</summary>
|
||||
public enum CellContentType
|
||||
{
|
||||
/// <summary>文本内容</summary>
|
||||
Text,
|
||||
/// <summary>图片纹理</summary>
|
||||
Image,
|
||||
/// <summary>预制体实例</summary>
|
||||
Prefab,
|
||||
}
|
||||
|
||||
/// <summary>图片纹理</summary>
|
||||
public Texture2D Image;
|
||||
/// <summary>
|
||||
/// 单元格数据模型——仅保存数据内容,不保存自身尺寸。
|
||||
/// 尺寸由渲染阶段的行列标题(行高/列宽)决定。
|
||||
/// 样式通过 StyleNamespace 字符串引用 StyleManager 中的命名空间。
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class XTableCellData
|
||||
{
|
||||
/// <summary>内容类型——决定渲染时使用 Text / Image / Prefab 中的哪一个</summary>
|
||||
public CellContentType ContentType;
|
||||
|
||||
/// <summary>预制体对象(用于嵌入复杂 UI 元素)</summary>
|
||||
public GameObject Prefab;
|
||||
/// <summary>文本内容(ContentType == Text 时生效)</summary>
|
||||
public string Text;
|
||||
|
||||
/// <summary>
|
||||
/// 样式命名空间——对应 StyleManager 中的命名空间。
|
||||
/// 为空或 "xeric_table_default" 时使用默认表格样式。
|
||||
/// 渲染时从此命名空间读取 /cell/bg/color、/cell/font/size 等路径。
|
||||
/// </summary>
|
||||
public string StyleNamespace;
|
||||
/// <summary>图片纹理(ContentType == Image 时生效)</summary>
|
||||
public Texture2D Image;
|
||||
|
||||
/// <summary>预制体实例从对象池取出时回调——外部可在此初始化实例内容</summary>
|
||||
[NonSerialized] public System.Action<GameObject> OnPrefabAcquire;
|
||||
/// <summary>预制体对象(ContentType == Prefab 时生效,用于嵌入复杂 UI 元素)</summary>
|
||||
public GameObject Prefab;
|
||||
|
||||
/// <summary>预制体实例归还对象池前回调——外部可在此清理引用</summary>
|
||||
[NonSerialized] public System.Action<GameObject> OnPrefabRelease;
|
||||
/// <summary>
|
||||
/// 样式命名空间——对应 StyleManager 中的命名空间。
|
||||
/// 为空或 "xeric_table_default" 时使用默认表格样式。
|
||||
/// 渲染时从此命名空间读取 /cell/bg/color、/cell/font/size 等路径。
|
||||
/// </summary>
|
||||
public string StyleNamespace;
|
||||
|
||||
public XTableCellData()
|
||||
{ }
|
||||
/// <summary>
|
||||
/// 单元格级别样式覆盖——通过命名空间 + 路径引用样式表中的值。
|
||||
/// 渲染时优先使用此样式路径派生颜色/尺寸(如 {StylePath}/bg/color),未设置时回退到 StyleNamespace。
|
||||
/// </summary>
|
||||
public StyleMember CellStyle;
|
||||
|
||||
public XTableCellData(string text) => Text = text;
|
||||
/// <summary>预制体实例从对象池取出时回调——外部可在此初始化实例内容</summary>
|
||||
[NonSerialized] public System.Action<GameObject> OnPrefabAcquire;
|
||||
|
||||
public XTableCellData(string text, string styleNamespace = null) : this(text) =>
|
||||
StyleNamespace = styleNamespace;
|
||||
/// <summary>预制体实例归还对象池前回调——外部可在此清理引用</summary>
|
||||
[NonSerialized] public System.Action<GameObject> OnPrefabRelease;
|
||||
|
||||
public XTableCellData(string text, Texture2D image, string styleNamespace = null) :
|
||||
this(text, styleNamespace) => Image = image;
|
||||
public XTableCellData()
|
||||
{ }
|
||||
|
||||
public void ClearEvent()
|
||||
{
|
||||
OnPrefabAcquire = null;
|
||||
OnPrefabRelease = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
public XTableCellData(string text) => Text = text;
|
||||
|
||||
public XTableCellData(string text, string styleNamespace = null) : this(text) =>
|
||||
StyleNamespace = styleNamespace;
|
||||
|
||||
public XTableCellData(string text, Texture2D image, string styleNamespace = null) :
|
||||
this(text, styleNamespace) => Image = image;
|
||||
|
||||
/// <summary>获取该单元格渲染时使用的样式命名空间(CellStyle 优先,否则 fallback 到 StyleNamespace)</summary>
|
||||
public string GetEffectiveStyleNamespace(string fallbackNamespace)
|
||||
{
|
||||
if (CellStyle != null && !string.IsNullOrEmpty(CellStyle.CurrentNamespace))
|
||||
return CellStyle.CurrentNamespace;
|
||||
if (!string.IsNullOrEmpty(StyleNamespace))
|
||||
return StyleNamespace;
|
||||
return fallbackNamespace;
|
||||
}
|
||||
|
||||
public void ClearEvent()
|
||||
{
|
||||
OnPrefabAcquire = null;
|
||||
OnPrefabRelease = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace XericUI.XTable.Rendering.Component
|
||||
/// <summary>共享活跃预制体映射表(由 XericUIActionTable 传入)</summary>
|
||||
public Dictionary<(int, int), GameObject> ActivePrefabMap;
|
||||
|
||||
/// <summary>Texture2D → Sprite 缓存,避免每帧分配</summary>
|
||||
private Dictionary<Texture2D, Sprite> m_SpriteCache;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 公开属性
|
||||
@@ -249,30 +252,46 @@ namespace XericUI.XTable.Rendering.Component
|
||||
|
||||
if (data == null) continue;
|
||||
|
||||
if (!string.IsNullOrEmpty(data.Text))
|
||||
switch (data.ContentType)
|
||||
{
|
||||
var txt = m_Assembler.GetText("cell_text", cellNS);
|
||||
txt.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
txt.Rect.sizeDelta = new Vector2(cellW - 8, 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 (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);
|
||||
case CellContentType.Text:
|
||||
if (!string.IsNullOrEmpty(data.Text))
|
||||
{
|
||||
var txt = m_Assembler.GetText("cell_text", cellNS);
|
||||
txt.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
txt.Rect.sizeDelta = new Vector2(cellW - 8, 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;
|
||||
}
|
||||
break;
|
||||
case CellContentType.Image:
|
||||
if (data.Image != null)
|
||||
{
|
||||
Sprite sprite = GetOrCreateSprite(data.Image);
|
||||
var img = m_Assembler.GetImage("cell_image", cellNS);
|
||||
img.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
img.Rect.sizeDelta = new Vector2(cellW - 8, 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);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -338,23 +357,39 @@ namespace XericUI.XTable.Rendering.Component
|
||||
|
||||
if (data == null) continue;
|
||||
|
||||
if (!string.IsNullOrEmpty(data.Text))
|
||||
switch (data.ContentType)
|
||||
{
|
||||
var txt = m_Assembler.GetText("cell_text", cellNS);
|
||||
txt.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
txt.Rect.sizeDelta = new Vector2(cellW - 8, cellH);
|
||||
txt.Text.text = data.Text;
|
||||
}
|
||||
|
||||
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);
|
||||
case CellContentType.Text:
|
||||
if (!string.IsNullOrEmpty(data.Text))
|
||||
{
|
||||
var txt = m_Assembler.GetText("cell_text", cellNS);
|
||||
txt.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
txt.Rect.sizeDelta = new Vector2(cellW - 8, cellH);
|
||||
txt.Text.text = data.Text;
|
||||
}
|
||||
break;
|
||||
case CellContentType.Image:
|
||||
if (data.Image != null)
|
||||
{
|
||||
Sprite sprite = GetOrCreateSprite(data.Image);
|
||||
var img = m_Assembler.GetImage("cell_image", cellNS);
|
||||
img.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
img.Rect.sizeDelta = new Vector2(cellW - 8, 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);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -362,6 +397,26 @@ namespace XericUI.XTable.Rendering.Component
|
||||
|
||||
#endregion
|
||||
|
||||
#region 辅助方法
|
||||
|
||||
/// <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 float CalcRowTopY(int row, float[] rowHeights)
|
||||
|
||||
@@ -76,6 +76,9 @@ namespace XericUI.XTable.Rendering.Component
|
||||
/// <summary>活跃预制体实例映射 (row, col) → instance,用于回调编排</summary>
|
||||
[System.NonSerialized] private Dictionary<(int, int), GameObject> m_ActivePrefabMap;
|
||||
|
||||
/// <summary>Texture2D → Sprite 缓存,避免每帧 Sprite.Create 分配</summary>
|
||||
[System.NonSerialized] private Dictionary<Texture2D, Sprite> m_SpriteCache;
|
||||
|
||||
/// <summary>表格四叉树——按 StyleNamespace 分区,渲染阶段查询可见象限</summary>
|
||||
[System.NonSerialized] private XTableQuadtree m_Quadtree;
|
||||
|
||||
@@ -250,26 +253,42 @@ namespace XericUI.XTable.Rendering.Component
|
||||
|
||||
if (data == null) continue;
|
||||
|
||||
if (!string.IsNullOrEmpty(data.Text))
|
||||
switch (data.ContentType)
|
||||
{
|
||||
var txt = m_Assembler.GetText("cell_text", cellNS);
|
||||
txt.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
txt.Rect.sizeDelta = new Vector2(cellW - 8, cellH);
|
||||
txt.Text.text = data.Text;
|
||||
txt.Text.color = GetCellFgColor(cellNS);
|
||||
txt.Text.fontSize = GetCellFontSize(cellNS);
|
||||
txt.Text.alignment = TextAlignmentOptions.Midline;
|
||||
txt.Text.font = GetCellFontAsset(cellNS) ?? txt.Text.font;
|
||||
}
|
||||
|
||||
if (data.Prefab != null)
|
||||
{
|
||||
GameObject instance = m_PrefabPool.Acquire(data.Prefab, row, col);
|
||||
RectTransform prt = instance.GetComponent<RectTransform>();
|
||||
prt.anchoredPosition = new Vector2(cellX, cellY);
|
||||
prt.sizeDelta = new Vector2(cellW, cellH);
|
||||
m_ActivePrefabMap[(row, col)] = instance;
|
||||
data.OnPrefabAcquire?.Invoke(instance);
|
||||
case CellContentType.Text:
|
||||
if (!string.IsNullOrEmpty(data.Text))
|
||||
{
|
||||
var txt = m_Assembler.GetText("cell_text", cellNS);
|
||||
txt.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
txt.Rect.sizeDelta = new Vector2(cellW - 8, cellH);
|
||||
txt.Text.text = data.Text;
|
||||
txt.Text.color = GetCellFgColor(cellNS);
|
||||
txt.Text.fontSize = GetCellFontSize(cellNS);
|
||||
txt.Text.alignment = TextAlignmentOptions.Midline;
|
||||
txt.Text.font = GetCellFontAsset(cellNS) ?? txt.Text.font;
|
||||
}
|
||||
break;
|
||||
case CellContentType.Image:
|
||||
if (data.Image != null)
|
||||
{
|
||||
Sprite sprite = GetOrCreateSprite(data.Image);
|
||||
var img = m_Assembler.GetImage("cell_image", cellNS);
|
||||
img.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
img.Rect.sizeDelta = new Vector2(cellW - 8, cellH);
|
||||
img.Image.sprite = sprite;
|
||||
}
|
||||
break;
|
||||
case CellContentType.Prefab:
|
||||
if (data.Prefab != null)
|
||||
{
|
||||
GameObject instance = m_PrefabPool.Acquire(data.Prefab, row, col);
|
||||
RectTransform prt = instance.GetComponent<RectTransform>();
|
||||
prt.anchoredPosition = new Vector2(cellX, cellY);
|
||||
prt.sizeDelta = new Vector2(cellW, cellH);
|
||||
m_ActivePrefabMap[(row, col)] = instance;
|
||||
data.OnPrefabAcquire?.Invoke(instance);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -333,22 +352,38 @@ namespace XericUI.XTable.Rendering.Component
|
||||
|
||||
if (data == null) continue;
|
||||
|
||||
if (!string.IsNullOrEmpty(data.Text))
|
||||
switch (data.ContentType)
|
||||
{
|
||||
var txt = m_Assembler.GetText("cell_text", cellNS);
|
||||
txt.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
txt.Rect.sizeDelta = new Vector2(cellW - 8, cellH);
|
||||
txt.Text.text = data.Text;
|
||||
}
|
||||
|
||||
if (data.Prefab != null)
|
||||
{
|
||||
GameObject instance = m_PrefabPool.Acquire(data.Prefab, row, col);
|
||||
RectTransform prt = instance.GetComponent<RectTransform>();
|
||||
prt.anchoredPosition = new Vector2(cellX, cellY);
|
||||
prt.sizeDelta = new Vector2(cellW, cellH);
|
||||
m_ActivePrefabMap[(row, col)] = instance;
|
||||
data.OnPrefabAcquire?.Invoke(instance);
|
||||
case CellContentType.Text:
|
||||
if (!string.IsNullOrEmpty(data.Text))
|
||||
{
|
||||
var txt = m_Assembler.GetText("cell_text", cellNS);
|
||||
txt.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
txt.Rect.sizeDelta = new Vector2(cellW - 8, cellH);
|
||||
txt.Text.text = data.Text;
|
||||
}
|
||||
break;
|
||||
case CellContentType.Image:
|
||||
if (data.Image != null)
|
||||
{
|
||||
Sprite sprite = GetOrCreateSprite(data.Image);
|
||||
var img = m_Assembler.GetImage("cell_image", cellNS);
|
||||
img.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
img.Rect.sizeDelta = new Vector2(cellW - 8, cellH);
|
||||
img.Image.sprite = sprite;
|
||||
}
|
||||
break;
|
||||
case CellContentType.Prefab:
|
||||
if (data.Prefab != null)
|
||||
{
|
||||
GameObject instance = m_PrefabPool.Acquire(data.Prefab, row, col);
|
||||
RectTransform prt = instance.GetComponent<RectTransform>();
|
||||
prt.anchoredPosition = new Vector2(cellX, cellY);
|
||||
prt.sizeDelta = new Vector2(cellW, cellH);
|
||||
m_ActivePrefabMap[(row, col)] = instance;
|
||||
data.OnPrefabAcquire?.Invoke(instance);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -517,38 +552,49 @@ namespace XericUI.XTable.Rendering.Component
|
||||
MarkDirty(TableDirtyType.DataChanged);
|
||||
}
|
||||
|
||||
/// <summary>设置文本内容(ContentType 自动设为 Text)</summary>
|
||||
public XTableCellData SetCellText(int row, int col, string text)
|
||||
{
|
||||
var data = TableData.GetOrCreateCell(row, col);
|
||||
data.Text = text;
|
||||
data.ContentType = CellContentType.Text;
|
||||
MarkDirty(TableDirtyType.DataChanged);
|
||||
return data;
|
||||
}
|
||||
|
||||
public XTableCellData GetCellData(int row, int col)
|
||||
=> TableData.GetOrCreateCell(row, col);
|
||||
|
||||
/// <summary>为指定单元格设置预制体</summary>
|
||||
public XTableCellData SetCellPrefab(int row, int col, GameObject prefab)
|
||||
{
|
||||
var data = TableData.GetOrCreateCell(row, col);
|
||||
data.Prefab = prefab;
|
||||
MarkDirty(TableDirtyType.DataChanged);
|
||||
/// <summary>设置图片纹理(ContentType 自动设为 Image)</summary>
|
||||
public XTableCellData SetCellImage(int row, int col, Texture2D image)
|
||||
{
|
||||
var data = TableData.GetOrCreateCell(row, col);
|
||||
data.Image = image;
|
||||
data.ContentType = CellContentType.Image;
|
||||
MarkDirty(TableDirtyType.DataChanged);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>清除指定单元格的预制体</summary>
|
||||
public void ClearCellPrefab(int row, int col)
|
||||
{
|
||||
var data = TableData.GetCell(row, col);
|
||||
if (data == null) return;
|
||||
data.Prefab = null;
|
||||
data.OnPrefabAcquire = null;
|
||||
data.OnPrefabRelease = null;
|
||||
MarkDirty(TableDirtyType.DataChanged);
|
||||
}
|
||||
/// <summary>设置预制体(ContentType 自动设为 Prefab)</summary>
|
||||
public XTableCellData SetCellPrefab(int row, int col, GameObject prefab)
|
||||
{
|
||||
var data = TableData.GetOrCreateCell(row, col);
|
||||
data.Prefab = prefab;
|
||||
data.ContentType = CellContentType.Prefab;
|
||||
MarkDirty(TableDirtyType.DataChanged);
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>设置单元格的样式命名空间</summary>
|
||||
/// <summary>设置单元格样式覆盖(StyleMember:命名空间 + 路径)</summary>
|
||||
public XTableCellData SetCellStyle(int row, int col, string styleNamespace, string stylePath)
|
||||
{
|
||||
var data = TableData.GetOrCreateCell(row, col);
|
||||
if (data.CellStyle == null)
|
||||
data.CellStyle = new XericLibrary.Runtime.SuperStyleSheet.StyleMember();
|
||||
data.CellStyle.CurrentNamespace = styleNamespace ?? "";
|
||||
data.CellStyle.StylePath = stylePath ?? "";
|
||||
MarkDirty(TableDirtyType.StyleChanged);
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>设置单元格的样式命名空间(兼容旧版,等同于 StyleNamespace 字段)</summary>
|
||||
public void SetCellStyleNamespace(int row, int col, string styleNamespace)
|
||||
{
|
||||
var data = TableData.GetOrCreateCell(row, col);
|
||||
@@ -556,10 +602,54 @@ namespace XericUI.XTable.Rendering.Component
|
||||
MarkDirty(TableDirtyType.StyleChanged);
|
||||
}
|
||||
|
||||
/// <summary>获取单元格的样式命名空间</summary>
|
||||
/// <summary>清除文本内容</summary>
|
||||
public void ClearCellText(int row, int col)
|
||||
{
|
||||
var data = TableData.GetCell(row, col);
|
||||
if (data == null) return;
|
||||
data.Text = null;
|
||||
if (data.ContentType == CellContentType.Text)
|
||||
data.ContentType = CellContentType.Text; // 保持类型不变,仅清空内容
|
||||
MarkDirty(TableDirtyType.DataChanged);
|
||||
}
|
||||
|
||||
/// <summary>清除图片纹理</summary>
|
||||
public void ClearCellImage(int row, int col)
|
||||
{
|
||||
var data = TableData.GetCell(row, col);
|
||||
if (data == null) return;
|
||||
data.Image = null;
|
||||
MarkDirty(TableDirtyType.DataChanged);
|
||||
}
|
||||
|
||||
/// <summary>清除预制体及委托</summary>
|
||||
public void ClearCellPrefab(int row, int col)
|
||||
{
|
||||
var data = TableData.GetCell(row, col);
|
||||
if (data == null) return;
|
||||
data.Prefab = null;
|
||||
data.OnPrefabAcquire = null;
|
||||
data.OnPrefabRelease = null;
|
||||
MarkDirty(TableDirtyType.DataChanged);
|
||||
}
|
||||
|
||||
/// <summary>清除单元格样式覆盖</summary>
|
||||
public void ClearCellStyle(int row, int col)
|
||||
{
|
||||
var data = TableData.GetCell(row, col);
|
||||
if (data == null) return;
|
||||
data.CellStyle = null;
|
||||
MarkDirty(TableDirtyType.StyleChanged);
|
||||
}
|
||||
|
||||
public XTableCellData GetCellData(int row, int col)
|
||||
=> TableData.GetOrCreateCell(row, col);
|
||||
|
||||
/// <summary>获取单元格的样式命名空间(含回退逻辑)</summary>
|
||||
public string GetCellStyleNamespace(int row, int col)
|
||||
{
|
||||
return TableData.GetCell(row, col)?.StyleNamespace ?? m_DefaultStyleNamespace;
|
||||
var data = TableData.GetCell(row, col);
|
||||
return data != null ? data.GetEffectiveStyleNamespace(m_DefaultStyleNamespace) : m_DefaultStyleNamespace;
|
||||
}
|
||||
|
||||
public void MergeCells(int startRow, int startCol, int rowSpan, int colSpan)
|
||||
@@ -1201,27 +1291,42 @@ namespace XericUI.XTable.Rendering.Component
|
||||
|
||||
if (data == null) continue;
|
||||
|
||||
if (!string.IsNullOrEmpty(data.Text))
|
||||
switch (data.ContentType)
|
||||
{
|
||||
var txt = m_Assembler.GetText("cell_text", cellNS);
|
||||
txt.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
txt.Rect.sizeDelta = new Vector2(cellW - 8, cellH);
|
||||
txt.Text.text = data.Text;
|
||||
txt.Text.color = GetCellFgColor(cellNS);
|
||||
txt.Text.fontSize = GetCellFontSize(cellNS);
|
||||
txt.Text.alignment = TextAlignmentOptions.Midline;
|
||||
txt.Text.font = GetCellFontAsset(cellNS) ?? txt.Text.font;
|
||||
}
|
||||
|
||||
// 预制体渲染
|
||||
if (data.Prefab != null)
|
||||
{
|
||||
GameObject instance = m_PrefabPool.Acquire(data.Prefab, r, c);
|
||||
RectTransform prt = instance.GetComponent<RectTransform>();
|
||||
prt.anchoredPosition = new Vector2(cellX, cellY);
|
||||
prt.sizeDelta = new Vector2(cellW, cellH);
|
||||
m_ActivePrefabMap[(r, c)] = instance;
|
||||
data.OnPrefabAcquire?.Invoke(instance);
|
||||
case CellContentType.Text:
|
||||
if (!string.IsNullOrEmpty(data.Text))
|
||||
{
|
||||
var txt = m_Assembler.GetText("cell_text", cellNS);
|
||||
txt.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
txt.Rect.sizeDelta = new Vector2(cellW - 8, cellH);
|
||||
txt.Text.text = data.Text;
|
||||
txt.Text.color = GetCellFgColor(cellNS);
|
||||
txt.Text.fontSize = GetCellFontSize(cellNS);
|
||||
txt.Text.alignment = TextAlignmentOptions.Midline;
|
||||
txt.Text.font = GetCellFontAsset(cellNS) ?? txt.Text.font;
|
||||
}
|
||||
break;
|
||||
case CellContentType.Image:
|
||||
if (data.Image != null)
|
||||
{
|
||||
Sprite sprite = GetOrCreateSprite(data.Image);
|
||||
var img = m_Assembler.GetImage("cell_image", cellNS);
|
||||
img.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
img.Rect.sizeDelta = new Vector2(cellW - 8, cellH);
|
||||
img.Image.sprite = sprite;
|
||||
}
|
||||
break;
|
||||
case CellContentType.Prefab:
|
||||
if (data.Prefab != null)
|
||||
{
|
||||
GameObject instance = m_PrefabPool.Acquire(data.Prefab, r, c);
|
||||
RectTransform prt = instance.GetComponent<RectTransform>();
|
||||
prt.anchoredPosition = new Vector2(cellX, cellY);
|
||||
prt.sizeDelta = new Vector2(cellW, cellH);
|
||||
m_ActivePrefabMap[(r, c)] = instance;
|
||||
data.OnPrefabAcquire?.Invoke(instance);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1287,24 +1392,39 @@ namespace XericUI.XTable.Rendering.Component
|
||||
|
||||
if (data == null) continue;
|
||||
|
||||
if (!string.IsNullOrEmpty(data.Text))
|
||||
switch (data.ContentType)
|
||||
{
|
||||
var txt = m_Assembler.GetText("cell_text", cellNS);
|
||||
txt.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
txt.Rect.sizeDelta = new Vector2(cellW - 8, cellH);
|
||||
txt.Text.text = data.Text;
|
||||
// 运行时样式由 StyleBoundElement 被动更新,此处仅设置文本内容
|
||||
}
|
||||
|
||||
// 预制体渲染
|
||||
if (data.Prefab != null)
|
||||
{
|
||||
GameObject instance = m_PrefabPool.Acquire(data.Prefab, r, c);
|
||||
RectTransform prt = instance.GetComponent<RectTransform>();
|
||||
prt.anchoredPosition = new Vector2(cellX, cellY);
|
||||
prt.sizeDelta = new Vector2(cellW, cellH);
|
||||
m_ActivePrefabMap[(r, c)] = instance;
|
||||
data.OnPrefabAcquire?.Invoke(instance);
|
||||
case CellContentType.Text:
|
||||
if (!string.IsNullOrEmpty(data.Text))
|
||||
{
|
||||
var txt = m_Assembler.GetText("cell_text", cellNS);
|
||||
txt.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
txt.Rect.sizeDelta = new Vector2(cellW - 8, cellH);
|
||||
txt.Text.text = data.Text;
|
||||
// 运行时样式由 StyleBoundElement 被动更新,此处仅设置文本内容
|
||||
}
|
||||
break;
|
||||
case CellContentType.Image:
|
||||
if (data.Image != null)
|
||||
{
|
||||
Sprite sprite = GetOrCreateSprite(data.Image);
|
||||
var img = m_Assembler.GetImage("cell_image", cellNS);
|
||||
img.Rect.anchoredPosition = new Vector2(cellX + 4, cellY);
|
||||
img.Rect.sizeDelta = new Vector2(cellW - 8, cellH);
|
||||
img.Image.sprite = sprite;
|
||||
}
|
||||
break;
|
||||
case CellContentType.Prefab:
|
||||
if (data.Prefab != null)
|
||||
{
|
||||
GameObject instance = m_PrefabPool.Acquire(data.Prefab, r, c);
|
||||
RectTransform prt = instance.GetComponent<RectTransform>();
|
||||
prt.anchoredPosition = new Vector2(cellX, cellY);
|
||||
prt.sizeDelta = new Vector2(cellW, cellH);
|
||||
m_ActivePrefabMap[(r, c)] = instance;
|
||||
data.OnPrefabAcquire?.Invoke(instance);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1330,6 +1450,22 @@ namespace XericUI.XTable.Rendering.Component
|
||||
return x;
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
|
||||
private void RecalculateTotalSize()
|
||||
{
|
||||
m_TotalWidth = 0;
|
||||
@@ -1466,7 +1602,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
|
||||
#region 其他
|
||||
|
||||
private void MarkDirty(TableDirtyType type)
|
||||
public void MarkDirty(TableDirtyType type)
|
||||
{
|
||||
m_DirtyFlag.Mark(type);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user