优化反射特性
This commit is contained in:
+31
-13
@@ -3,34 +3,52 @@ using System;
|
||||
namespace XericUI.ReflectionUIGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// 预制体覆盖特性
|
||||
/// 覆盖对应 Entry 或普通字段生成 UI 时使用的预制体名称
|
||||
/// 字段显示名称特性
|
||||
/// 设置字段在 UI 上的显示标签、单位文本和格式化字符串
|
||||
///
|
||||
/// 使用示例:
|
||||
/// [XuiavrgFieldPrefabOverride("CustomSpeedPrefab")] public float speed;
|
||||
/// [XuiavrgFieldName("角色名称")]
|
||||
/// public string playerName = "勇者";
|
||||
///
|
||||
/// Manager 在 GenerateUI 阶段会优先使用此名称查找 PropertyGroup
|
||||
/// [XuiavrgFieldName("速度", "m/s", "{0:F1}")]
|
||||
/// public float speed = 5f;
|
||||
///
|
||||
/// 字段定义:
|
||||
/// - labelName: UI 上的显示标签(必填)
|
||||
/// - unitLabelName: 单位文本(可选),如 "m/s"、"%"、"px"
|
||||
/// - formatText: 格式化字符串(可选),如 "{0:F2}",控制值在 UI 上的显示格式
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
|
||||
public class XuiavrgFieldNameAttribute : Attribute, IXuiavrgAttribute
|
||||
{
|
||||
/// <summary>覆盖的预制体组名称</summary>
|
||||
public readonly string PrefabGroupName;
|
||||
/// <summary>字段的显示标签</summary>
|
||||
public readonly string LabelName;
|
||||
|
||||
/// <summary>单位文本(可选)</summary>
|
||||
public readonly string UnitLabelName;
|
||||
|
||||
/// <summary>格式化字符串(可选),如 "{0:F2}"</summary>
|
||||
public readonly string FormatText;
|
||||
|
||||
/// <summary>
|
||||
/// 创建预制体覆盖标记
|
||||
/// 创建字段显示名称标记
|
||||
/// </summary>
|
||||
/// <param name="prefabGroupName">
|
||||
/// 目标预制体名称,在 AvrgTypePrefabMappingConfig 中查找匹配
|
||||
/// </param>
|
||||
public XuiavrgFieldNameAttribute(string prefabGroupName)
|
||||
/// <param name="labelName">UI 上的显示标签</param>
|
||||
/// <param name="unitLabelName">可选的单位文本,如 "m/s"</param>
|
||||
/// <param name="formatText">可选的格式化字符串,如 "{0:F2}"</param>
|
||||
public XuiavrgFieldNameAttribute(string labelName, string unitLabelName = null, string formatText = null)
|
||||
{
|
||||
PrefabGroupName = prefabGroupName;
|
||||
LabelName = labelName;
|
||||
UnitLabelName = unitLabelName;
|
||||
FormatText = formatText;
|
||||
}
|
||||
|
||||
public void BindMetaData(AvrgMemberMetaData metaData)
|
||||
{
|
||||
metaData.PrefabOverrideName = PrefabGroupName;
|
||||
metaData.LabelName = LabelName;
|
||||
metaData.UnitLabelName = UnitLabelName;
|
||||
metaData.FormatText = FormatText;
|
||||
// PrefabOverrideName 已移除 — 由类型+Tag 匹配替代
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8254aa7ff8b5fe443b04eb4b30a063d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+8
-5
@@ -33,16 +33,19 @@ namespace XericUI.ReflectionUIGenerator
|
||||
/// <summary>是否启用无效值状态检查</summary>
|
||||
public bool ValidateInvalid { get; set; }
|
||||
|
||||
public XuiavrgPropertyCheckAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建必填检查标记
|
||||
/// </summary>
|
||||
public XuiavrgPropertyCheckAttribute(bool required)
|
||||
/// <param name="required">是否必填</param>
|
||||
/// <param name="validateReasonable">是否启用合理值范围检查</param>
|
||||
/// <param name="validateWarning">是否启用警告状态检查</param>
|
||||
/// <param name="validateInvalid">是否启用无效值状态检查</param>
|
||||
public XuiavrgPropertyCheckAttribute(bool required = true, bool validateReasonable = false, bool validateWarning = false, bool validateInvalid = false)
|
||||
{
|
||||
Required = required;
|
||||
ValidateReasonable = validateReasonable;
|
||||
ValidateWarning = validateWarning;
|
||||
ValidateInvalid = validateInvalid;
|
||||
}
|
||||
|
||||
public void BindMetaData(AvrgMemberMetaData metaData)
|
||||
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace XericUI.ReflectionUIGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// 拆分属性标注
|
||||
/// 将一个复合类型(如 Vector2)拆分为多个子属性,分别绑定到不同的 UI 元素
|
||||
///
|
||||
/// 使用示例:
|
||||
/// [XuiavrgFieldEntryGroup("speed")]
|
||||
/// [XuiavrgSplit("x", "最小")]
|
||||
/// [XuiavrgSplit("y", "最大")]
|
||||
/// public Vector2 speedRange = new Vector2(0, 100);
|
||||
///
|
||||
/// 上述代码创建一个 "speed" 编组的 Entry,内部包含两个子绑定:
|
||||
/// speedRange.x 绑定到 UI 的"最小"输入,speedRange.y 绑定到"最大"输入
|
||||
/// 子绑定通过 XUIAvrgMDValue.BindingSlots 与预制体上的 UI 组件匹配
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)]
|
||||
public class XuiavrgSplitAttribute : Attribute, IXuiavrgAttribute
|
||||
{
|
||||
/// <summary>子属性路径(如 "x"、"y"),访问父值上的子字段/属性</summary>
|
||||
public readonly string PropertyPath;
|
||||
|
||||
/// <summary>可选的显示标签</summary>
|
||||
public readonly string DisplayLabel;
|
||||
|
||||
/// <summary>
|
||||
/// 创建拆分属性标记
|
||||
/// </summary>
|
||||
/// <param name="propertyPath">子属性路径(如 Vector2 的 "x" 或 "y")</param>
|
||||
/// <param name="displayLabel">可选的显示标签(为空时自动推导)</param>
|
||||
public XuiavrgSplitAttribute(string propertyPath, string displayLabel = null)
|
||||
{
|
||||
PropertyPath = propertyPath;
|
||||
DisplayLabel = displayLabel;
|
||||
}
|
||||
|
||||
public void BindMetaData(AvrgMemberMetaData metaData)
|
||||
{
|
||||
// 创建子元数据
|
||||
var subMetaData = new AvrgMemberMetaData
|
||||
{
|
||||
MemberName = $"{metaData.MemberName}.{PropertyPath}",
|
||||
PropertyPath = PropertyPath,
|
||||
LabelName = DisplayLabel ?? PropertyPath,
|
||||
TargetInstance = null, // 由运行时闭包解析
|
||||
Hide = metaData.Hide,
|
||||
Required = metaData.Required,
|
||||
FieldOrder = metaData.FieldOrder,
|
||||
};
|
||||
|
||||
// 通过反射解析子属性的值类型
|
||||
if (metaData.ValueType != null)
|
||||
{
|
||||
var subType = ResolveSubPropertyType(metaData.ValueType, PropertyPath);
|
||||
if (subType != null)
|
||||
subMetaData.ValueType = subType;
|
||||
}
|
||||
|
||||
// 添加到父元数据的子元数据列表
|
||||
if (metaData.SubMetaDataList == null)
|
||||
metaData.SubMetaDataList = new List<AvrgMemberMetaData>();
|
||||
|
||||
metaData.SubMetaDataList.Add(subMetaData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过反射解析子属性的类型
|
||||
/// </summary>
|
||||
private static Type ResolveSubPropertyType(Type parentType, string propertyPath)
|
||||
{
|
||||
if (parentType == null || string.IsNullOrEmpty(propertyPath))
|
||||
return null;
|
||||
|
||||
// 仅支持单层路径
|
||||
if (propertyPath.Contains('/'))
|
||||
return null;
|
||||
|
||||
var field = parentType.GetField(propertyPath);
|
||||
if (field != null) return field.FieldType;
|
||||
|
||||
var prop = parentType.GetProperty(propertyPath);
|
||||
if (prop != null) return prop.PropertyType;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d1ecca25a43f5b24d878a1f88278b289
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user