添加了默认实例场景文件,默认示例文件。
优化了属性组的界面
This commit is contained in:
+4
-3
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -13,10 +13,11 @@ using Object = UnityEngine.Object;
|
||||
namespace XericUI.ReflectionUIGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// 属性映射器
|
||||
/// [已弃用] 属性映射器。请使用 XuiavrgPropertyGroupScriptableObject 替代。
|
||||
/// 功能已整合到 PropertyGroup 中,此类保留仅用于向后兼容。
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[CreateAssetMenu(fileName = "Xeric UI avr Property", menuName = "Xeric Library/UI Action Vessel/Reflection UI Gen/UI avr Property", order = 10)]
|
||||
[Obsolete("Use XuiavrgPropertyGroupScriptableObject instead. Property mapping is now integrated directly into the group.")]
|
||||
public class XuiavrPropertyScriptableObject : ScriptableObject
|
||||
{
|
||||
#if ODIN_INSPECTOR
|
||||
|
||||
@@ -43,11 +43,11 @@ namespace XericUI.ReflectionUIGenerator
|
||||
|
||||
if (!_propertyGroupPools.TryGetValue(group, out var pool))
|
||||
{
|
||||
var firstPrefab = group.FirstOrDefault()?.prefab;
|
||||
var prefab = group.prefab;
|
||||
pool = new ObjectPool<GameObject>(
|
||||
createFunc: () =>
|
||||
firstPrefab != null
|
||||
? Object.Instantiate(firstPrefab, transform)
|
||||
prefab != null
|
||||
? Object.Instantiate(prefab, transform)
|
||||
: new GameObject("PropertyItem", typeof(RectTransform)),
|
||||
actionOnGet: go => go.SetActive(true),
|
||||
actionOnRelease: go => go.SetActive(false),
|
||||
@@ -97,6 +97,15 @@ namespace XericUI.ReflectionUIGenerator
|
||||
|
||||
#region 字段
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("当前使用的 UI 主题名称。切换主题会立即销毁所有已生成 UI 和对象池,需重新 BuildEntries + GenerateUI")]
|
||||
private string _currentTheme = XuiavrgPropertyGroupScriptableObject.DefaultThemeName;
|
||||
|
||||
/// <summary>
|
||||
/// 当前 UI 主题名称
|
||||
/// </summary>
|
||||
public string CurrentTheme => _currentTheme;
|
||||
|
||||
/// <summary>
|
||||
/// 当前活跃的 Entry 列表
|
||||
/// </summary>
|
||||
@@ -107,6 +116,23 @@ namespace XericUI.ReflectionUIGenerator
|
||||
/// </summary>
|
||||
public object CurrentPayload { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 切换 UI 主题。会立即销毁所有已生成 UI 和对象池。
|
||||
/// 调用后需重新 BuildEntries + GenerateUI。
|
||||
/// </summary>
|
||||
/// <param name="themeName">新的主题名称</param>
|
||||
public void SetTheme(string themeName)
|
||||
{
|
||||
if (_currentTheme == themeName) return;
|
||||
|
||||
_currentTheme = string.IsNullOrEmpty(themeName)
|
||||
? XuiavrgPropertyGroupScriptableObject.DefaultThemeName
|
||||
: themeName;
|
||||
|
||||
// 销毁所有已生成 UI 和对象池
|
||||
ClearAll();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 核心生命周期
|
||||
@@ -321,18 +347,18 @@ namespace XericUI.ReflectionUIGenerator
|
||||
|
||||
/// <summary>
|
||||
/// 解析 Entry 对应的 PropertyGroup
|
||||
/// 优先使用 PrefabOverrideName,否则按 Tag 匹配
|
||||
/// 优先使用 PrefabOverrideName,否则按 Tag 匹配,所有查找在 currentTheme 下进行
|
||||
/// </summary>
|
||||
private XuiavrgPropertyGroupScriptableObject ResolvePropertyGroup(IFieldEntry entry)
|
||||
{
|
||||
// 1. 优先检查 PrefabOverrideName
|
||||
// 1. 优先检查 PrefabOverrideName(按主题 + UI 名称查找)
|
||||
if (!string.IsNullOrEmpty(entry.PrefabOverrideName))
|
||||
{
|
||||
var overrideGroup = XuiavrgPropertyGroupScriptableObject.FindGroupByName(entry.PrefabOverrideName);
|
||||
var overrideGroup = XuiavrgPropertyGroupScriptableObject.FindGroupByUiName(_currentTheme, entry.PrefabOverrideName);
|
||||
if (overrideGroup != null) return overrideGroup;
|
||||
}
|
||||
|
||||
// 2. 按 Tag 查找匹配的组
|
||||
// 2. 按 Tag 查找匹配的组(在当前主题下)
|
||||
if (entry.Tag != XuiavrgFieldTag.None)
|
||||
{
|
||||
var tags = new List<XuiavrgFieldTag> { entry.Tag };
|
||||
@@ -346,12 +372,12 @@ namespace XericUI.ReflectionUIGenerator
|
||||
}
|
||||
}
|
||||
|
||||
var matchedGroup = XuiavrgPropertyGroupScriptableObject.FindGroupByTags(tags.ToArray());
|
||||
var matchedGroup = XuiavrgPropertyGroupScriptableObject.FindGroup(_currentTheme, tags.ToArray());
|
||||
if (matchedGroup != null) return matchedGroup;
|
||||
}
|
||||
|
||||
// 3. 回退到通用匹配
|
||||
return XuiavrgPropertyGroupScriptableObject.FindGroupByName("Default");
|
||||
// 3. 回退到当前主题下的 "Default" UI 名称
|
||||
return XuiavrgPropertyGroupScriptableObject.FindGroupByUiName(_currentTheme, "Default");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
+153
-86
@@ -1,64 +1,169 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace XericUI.ReflectionUIGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// 界面属性编组
|
||||
/// 提供预制体与 UI 标记的绑定,支持全局静态访问
|
||||
///
|
||||
/// 将一种 C# 数据类型与一个 UI 预制体绑定,并归属于一个主题。
|
||||
/// 类似 Newtonsoft.Json 的 Converter 概念 — 针对特定 Type,指定特定的 UI 模板。
|
||||
///
|
||||
/// 同一类型可以有多个不同 uiName/主题的重载(如 "简单输入框" vs "带标签的输入框")。
|
||||
/// Manager 根据当前主题名 + 字段 Tag 自动匹配对应的编组。
|
||||
///
|
||||
/// 全局注册表以 themeName 为键分组管理,OnEnable/OnDisable 自动注册/注销。
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[CreateAssetMenu(fileName = "Xeric UI avr Property group", menuName = "Xeric Library/UI Action Vessel/Reflection UI Gen/UI avr Property Group", order = 10)]
|
||||
public class XuiavrgPropertyGroupScriptableObject : ScriptableObject, IList<XuiavrPropertyScriptableObject>
|
||||
public class XuiavrgPropertyGroupScriptableObject : ScriptableObject
|
||||
{
|
||||
#region 全局注册表
|
||||
|
||||
/// <summary>
|
||||
/// 全局预制体组列表
|
||||
/// 所有 PropertyGroupScriptableObject 在 OnEnable 时自动注册,OnDisable 时自动注销
|
||||
/// 全局预制体组字典,以主题名称为键分组
|
||||
/// </summary>
|
||||
internal static List<XuiavrgPropertyGroupScriptableObject> GlobalPrefabList
|
||||
= new List<XuiavrgPropertyGroupScriptableObject>();
|
||||
internal static Dictionary<string, List<XuiavrgPropertyGroupScriptableObject>> GlobalPrefabDict
|
||||
= new Dictionary<string, List<XuiavrgPropertyGroupScriptableObject>>();
|
||||
|
||||
/// <summary>
|
||||
/// 根据组名查找预制体组
|
||||
/// 根据主题名获取该主题下所有编组
|
||||
/// </summary>
|
||||
public static XuiavrgPropertyGroupScriptableObject FindGroupByName(string groupName)
|
||||
public static List<XuiavrgPropertyGroupScriptableObject> GetGroupsByTheme(string themeName)
|
||||
{
|
||||
return GlobalPrefabList.FirstOrDefault(g => g.groupName == groupName);
|
||||
if (string.IsNullOrEmpty(themeName))
|
||||
themeName = DefaultThemeName;
|
||||
|
||||
GlobalPrefabDict.TryGetValue(themeName, out var list);
|
||||
return list ?? new List<XuiavrgPropertyGroupScriptableObject>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找包含指定标记的预制体组
|
||||
/// 根据主题名 + 标记查找编组
|
||||
/// </summary>
|
||||
public static List<XuiavrgPropertyGroupScriptableObject> FindGroupsByTag(XuiavrgFieldTag tag)
|
||||
public static XuiavrgPropertyGroupScriptableObject FindGroup(string themeName, params XuiavrgFieldTag[] tags)
|
||||
{
|
||||
return GlobalPrefabList.Where(g => g.supportedTags.Contains(tag)).ToList();
|
||||
var groups = GetGroupsByTheme(themeName);
|
||||
return groups.FirstOrDefault(g => tags.All(t => g.supportedTags.Contains(t)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找同时包含所有指定标记的预制体组
|
||||
/// 根据主题名 + UI 名称查找编组
|
||||
/// </summary>
|
||||
public static XuiavrgPropertyGroupScriptableObject FindGroupByTags(params XuiavrgFieldTag[] tags)
|
||||
public static XuiavrgPropertyGroupScriptableObject FindGroupByUiName(string themeName, string uiName)
|
||||
{
|
||||
return GlobalPrefabList.FirstOrDefault(g =>
|
||||
tags.All(t => g.supportedTags.Contains(t)));
|
||||
var groups = GetGroupsByTheme(themeName);
|
||||
return groups.FirstOrDefault(g => g.uiName == uiName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据主题名 + 绑定类型查找所有匹配的编组
|
||||
/// </summary>
|
||||
public static List<XuiavrgPropertyGroupScriptableObject> FindGroupsByType(string themeName, string valueTypeName)
|
||||
{
|
||||
var groups = GetGroupsByTheme(themeName);
|
||||
return groups.Where(g => g.valueTypeName == valueTypeName).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 默认主题名称
|
||||
/// </summary>
|
||||
public const string DefaultThemeName = "Default";
|
||||
|
||||
#endregion
|
||||
|
||||
#region 字段
|
||||
#region 属性字段
|
||||
|
||||
/// <summary>预制体组名称(用于 XuiavrgFieldPrefabOverride 匹配)</summary>
|
||||
public string groupName;
|
||||
/// <summary>
|
||||
/// 主题名称。同一主题下的 UI 组件共享统一风格。
|
||||
/// </summary>
|
||||
[Tooltip("主题名称。同一主题下的 UI 组件共享统一风格。Manager 根据其 currentTheme 查找对应编组")]
|
||||
public string themeName = DefaultThemeName;
|
||||
|
||||
/// <summary>此组支持的功能标记集合</summary>
|
||||
/// <summary>
|
||||
/// UI 个体名称。同一类型可有多个不同名称的重载。
|
||||
/// 在数据字段上通过 XuiavrgFieldPrefabOverride 按此名称指定。
|
||||
/// </summary>
|
||||
[Tooltip("UI 个体名称。用于 XuiavrgFieldPrefabOverride 按名指定,同一类型可有多个重载")]
|
||||
public string uiName = "Default";
|
||||
|
||||
/// <summary>
|
||||
/// 此编组绑定的 C# 数据类型全名(如 System.Single、System.String)
|
||||
/// </summary>
|
||||
[Tooltip("绑定的 C# 数据类型全名,如 System.Single、System.Boolean")]
|
||||
public string valueTypeName = "System.Single";
|
||||
|
||||
/// <summary>
|
||||
/// 解析后的类型缓存
|
||||
/// </summary>
|
||||
public Type ValueType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_valueType != null) return _valueType;
|
||||
if (!string.IsNullOrEmpty(valueTypeName))
|
||||
_valueType = Type.GetType(valueTypeName);
|
||||
return _valueType;
|
||||
}
|
||||
}
|
||||
private Type _valueType;
|
||||
|
||||
/// <summary>
|
||||
/// 对应的 UI 预制体
|
||||
/// </summary>
|
||||
[Tooltip("拖入 UI 预制体,系统会自动扫描其中的 IXuiavrgFieldTagProvider 组件")]
|
||||
public GameObject prefab;
|
||||
|
||||
/// <summary>
|
||||
/// 此编组支持的 UI 功能标记集合
|
||||
/// </summary>
|
||||
[Tooltip("此编组包含的 UI 功能标记。Manager 根据字段 Tag 匹配对应编组")]
|
||||
public List<XuiavrgFieldTag> supportedTags = new List<XuiavrgFieldTag>();
|
||||
|
||||
public List<XuiavrPropertyScriptableObject> propertys = new List<XuiavrPropertyScriptableObject>();
|
||||
#endregion
|
||||
|
||||
#region 组件自动识别(运行时 + Editor 共用)
|
||||
|
||||
/// <summary>
|
||||
/// 从预制体中自动扫描到的 IXuiavrgFieldTagProvider 组件列表(非序列化,仅供 Editor 展示)
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public List<Component> detectedComponents = new List<Component>();
|
||||
|
||||
/// <summary>
|
||||
/// 重新扫描预制体中的标记组件
|
||||
/// </summary>
|
||||
public void ScanPrefabComponents()
|
||||
{
|
||||
detectedComponents.Clear();
|
||||
if (prefab == null) return;
|
||||
|
||||
var components = prefab.GetComponentsInChildren<Component>(true);
|
||||
foreach (var comp in components)
|
||||
{
|
||||
if (comp is IXuiavrgFieldTagProvider tagProvider && tagProvider.EntryTag != XuiavrgFieldTag.None)
|
||||
{
|
||||
detectedComponents.Add(comp);
|
||||
}
|
||||
}
|
||||
|
||||
// 自动同步 supportedTags
|
||||
HashSet<XuiavrgFieldTag> autoTags = new HashSet<XuiavrgFieldTag>();
|
||||
foreach (var comp in detectedComponents)
|
||||
{
|
||||
if (comp is IXuiavrgFieldTagProvider tp && tp.EntryTag != XuiavrgFieldTag.None)
|
||||
autoTags.Add(tp.EntryTag);
|
||||
}
|
||||
|
||||
foreach (var tag in autoTags)
|
||||
{
|
||||
if (!supportedTags.Contains(tag))
|
||||
supportedTags.Add(tag);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -66,75 +171,37 @@ namespace XericUI.ReflectionUIGenerator
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
if (!GlobalPrefabList.Contains(this))
|
||||
GlobalPrefabList.Add(this);
|
||||
RegisterToGlobalDict();
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
GlobalPrefabList.Remove(this);
|
||||
UnregisterFromGlobalDict();
|
||||
}
|
||||
|
||||
private void RegisterToGlobalDict()
|
||||
{
|
||||
string key = string.IsNullOrEmpty(themeName) ? DefaultThemeName : themeName;
|
||||
if (!GlobalPrefabDict.TryGetValue(key, out var list))
|
||||
{
|
||||
list = new List<XuiavrgPropertyGroupScriptableObject>();
|
||||
GlobalPrefabDict[key] = list;
|
||||
}
|
||||
if (!list.Contains(this))
|
||||
list.Add(this);
|
||||
}
|
||||
|
||||
private void UnregisterFromGlobalDict()
|
||||
{
|
||||
string key = string.IsNullOrEmpty(themeName) ? DefaultThemeName : themeName;
|
||||
if (GlobalPrefabDict.TryGetValue(key, out var list))
|
||||
{
|
||||
list.Remove(this);
|
||||
if (list.Count == 0)
|
||||
GlobalPrefabDict.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public IEnumerator<XuiavrPropertyScriptableObject> GetEnumerator()
|
||||
{
|
||||
return propertys.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable)propertys).GetEnumerator();
|
||||
}
|
||||
|
||||
public void Add(XuiavrPropertyScriptableObject item)
|
||||
{
|
||||
propertys.Add(item);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
propertys.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(XuiavrPropertyScriptableObject item)
|
||||
{
|
||||
return propertys.Contains(item);
|
||||
}
|
||||
|
||||
public void CopyTo(XuiavrPropertyScriptableObject[] array, int arrayIndex)
|
||||
{
|
||||
propertys.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public bool Remove(XuiavrPropertyScriptableObject item)
|
||||
{
|
||||
return propertys.Remove(item);
|
||||
}
|
||||
|
||||
public int Count => propertys.Count;
|
||||
|
||||
public bool IsReadOnly => true;
|
||||
|
||||
public int IndexOf(XuiavrPropertyScriptableObject item)
|
||||
{
|
||||
return propertys.IndexOf(item);
|
||||
}
|
||||
|
||||
public void Insert(int index, XuiavrPropertyScriptableObject item)
|
||||
{
|
||||
propertys.Insert(index, item);
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
propertys.RemoveAt(index);
|
||||
}
|
||||
|
||||
public XuiavrPropertyScriptableObject this[int index]
|
||||
{
|
||||
get => propertys[index];
|
||||
set => propertys[index] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user