From 283a4442280b48ee40686f2335c0bef850460d8b Mon Sep 17 00:00:00 2001
From: LiRuoChen <571244399@qq.com>
Date: Fri, 24 Apr 2026 19:42:01 +0800
Subject: [PATCH] =?UTF-8?q?=E5=B1=9E=E6=80=A7=E5=8F=8D=E5=B0=84=E7=94=9F?=
=?UTF-8?q?=E6=88=90=E7=95=8C=E9=9D=A2=E5=9F=BA=E6=9C=AC=E6=A1=86=E6=9E=B6?=
=?UTF-8?q?=E3=80=82=20=E4=BF=AE=E5=A4=8D=E6=87=92=E5=8A=A0=E8=BD=BD?=
=?UTF-8?q?=E6=A1=86=E7=9A=84=E5=B8=83=E5=B1=80=E9=97=AE=E9=A2=98=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Runtime/Helper/GridLayoutCalculator.cs | 28 +-
.../{Resource.meta => Resources.meta} | 0
.../Resources/Config.meta | 8 +
.../{Resource => Resources}/Prefabs.meta | 0
.../{Resource => Resources}/Sprites.meta | 0
.../Sprites/borderGrey32-4.png | Bin
.../Sprites/borderGrey32-4.png.meta | 0
.../Scripts/IXuiavrgAttribute.cs | 7 +
.../Scripts/IXuiavrgAttribute.cs.meta | 3 +
.../Scripts/XuiavrPropertyScriptableObject.cs | 107 ++++++
.../XuiavrPropertyScriptableObject.cs.meta | 3 +
.../Scripts/XuiavrgAttribute.cs | 77 ++++-
.../Scripts/XuiavrgHideAttribute.cs | 28 ++
.../Scripts/XuiavrgHideAttribute.cs.meta | 3 +
.../Scripts/XuiavrgInspectorManager.cs | 119 +++++++
...s.meta => XuiavrgInspectorManager.cs.meta} | 0
.../Scripts/XuiavrgInspectorProperty.cs | 142 ++++++++
.../Scripts/XuiavrgInspectorProperty.cs.meta | 3 +
.../Scripts/XuiavrgLocator.cs | 305 ++++++++++++++++++
...Locator.cs.meta => XuiavrgLocator.cs.meta} | 0
.../Scripts/XuiavrgManager.cs | 30 --
.../Scripts/XuiavrgPooledLocator.cs | 14 -
.../XuiavrgPropertyGroupScriptableObject.cs | 77 +++++
...iavrgPropertyGroupScriptableObject.cs.meta | 3 +
.../Scripts/XuiavrgUtilities.cs | 19 +-
Runtime/OverrideLayout/XericScrollRect.cs | 43 ++-
26 files changed, 953 insertions(+), 66 deletions(-)
rename Runtime/InterfaceAttributeReflectionGenerator/{Resource.meta => Resources.meta} (100%)
create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Resources/Config.meta
rename Runtime/InterfaceAttributeReflectionGenerator/{Resource => Resources}/Prefabs.meta (100%)
rename Runtime/InterfaceAttributeReflectionGenerator/{Resource => Resources}/Sprites.meta (100%)
rename Runtime/InterfaceAttributeReflectionGenerator/{Resource => Resources}/Sprites/borderGrey32-4.png (100%)
rename Runtime/InterfaceAttributeReflectionGenerator/{Resource => Resources}/Sprites/borderGrey32-4.png.meta (100%)
create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/IXuiavrgAttribute.cs
create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/IXuiavrgAttribute.cs.meta
create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrPropertyScriptableObject.cs
create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrPropertyScriptableObject.cs.meta
create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgHideAttribute.cs
create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgHideAttribute.cs.meta
create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorManager.cs
rename Runtime/InterfaceAttributeReflectionGenerator/Scripts/{XuiavrgManager.cs.meta => XuiavrgInspectorManager.cs.meta} (100%)
create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorProperty.cs
create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorProperty.cs.meta
create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgLocator.cs
rename Runtime/InterfaceAttributeReflectionGenerator/Scripts/{XuiavrgPooledLocator.cs.meta => XuiavrgLocator.cs.meta} (100%)
delete mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgManager.cs
delete mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgPooledLocator.cs
create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgPropertyGroupScriptableObject.cs
create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgPropertyGroupScriptableObject.cs.meta
diff --git a/Runtime/Helper/GridLayoutCalculator.cs b/Runtime/Helper/GridLayoutCalculator.cs
index 200ca0e..e1ac234 100644
--- a/Runtime/Helper/GridLayoutCalculator.cs
+++ b/Runtime/Helper/GridLayoutCalculator.cs
@@ -19,6 +19,17 @@ namespace XericUI.Helper
///
/// 计算所有项目的布局
///
+ /// 子项数量
+ /// 所需尺寸
+ /// 单元尺寸
+ /// 单元空隙
+ /// 外围空隙
+ /// 起始角
+ /// 起始轴
+ /// 容器尺寸
+ /// 需要的列数
+ /// 子项对齐
+ ///
public static List CalculateGridLayout(
List layoutItems,
int childCount,
@@ -143,13 +154,13 @@ namespace XericUI.Helper
float baseOffset;
if (axis == 0) // X轴
{
- // 如果startCorner在右侧,基准点应该是padding.right
+ // 如果startCorner在右侧,基准点应该是availableSpace - padding.right - requiredSpace
int cornerX = (int)startCorner % 2;
baseOffset = (cornerX == 0) ? padding.left : (availableSpace - padding.right - requiredSpace);
}
else // Y轴
{
- // 如果startCorner在底部,基准点应该是padding.bottom
+ // 如果startCorner在底部,基准点应该是availableSpace - padding.bottom - requiredSpace
int cornerY = (int)startCorner / 2;
baseOffset = (cornerY == 0) ? padding.top : (availableSpace - padding.bottom - requiredSpace);
}
@@ -176,10 +187,12 @@ namespace XericUI.Helper
if (startAxis == GridLayoutGroup.Axis.Horizontal)
{
if (constraint == GridLayoutGroup.Constraint.FixedRowCount &&
- childCount - index <= childrenToMove)
+ childrenToMove > 0 && childCount - index <= childrenToMove)
{
+ // 计算偏移量,确保gridY不会为负数
+ int offset = childCount - index - 1;
gridX = 0;
- gridY = constraintCount - (childCount - index);
+ gridY = Mathf.Min(offset, constraintCount - 1);
}
else
{
@@ -190,9 +203,11 @@ namespace XericUI.Helper
else
{
if (constraint == GridLayoutGroup.Constraint.FixedColumnCount &&
- childCount - index <= childrenToMove)
+ childrenToMove > 0 && childCount - index <= childrenToMove)
{
- gridX = constraintCount - (childCount - index);
+ // 计算偏移量,确保gridX不会为负数
+ int offset = childCount - index - 1;
+ gridX = Mathf.Min(offset, constraintCount - 1);
gridY = 0;
}
else
@@ -201,7 +216,6 @@ namespace XericUI.Helper
gridY = index % cellCountY;
}
}
-
}
private static int CalculateChildrenToMove(
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Resource.meta b/Runtime/InterfaceAttributeReflectionGenerator/Resources.meta
similarity index 100%
rename from Runtime/InterfaceAttributeReflectionGenerator/Resource.meta
rename to Runtime/InterfaceAttributeReflectionGenerator/Resources.meta
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Resources/Config.meta b/Runtime/InterfaceAttributeReflectionGenerator/Resources/Config.meta
new file mode 100644
index 0000000..af0ca65
--- /dev/null
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Resources/Config.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5661a6f69ad8f9e4a8085712f4ac7e38
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Resource/Prefabs.meta b/Runtime/InterfaceAttributeReflectionGenerator/Resources/Prefabs.meta
similarity index 100%
rename from Runtime/InterfaceAttributeReflectionGenerator/Resource/Prefabs.meta
rename to Runtime/InterfaceAttributeReflectionGenerator/Resources/Prefabs.meta
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Resource/Sprites.meta b/Runtime/InterfaceAttributeReflectionGenerator/Resources/Sprites.meta
similarity index 100%
rename from Runtime/InterfaceAttributeReflectionGenerator/Resource/Sprites.meta
rename to Runtime/InterfaceAttributeReflectionGenerator/Resources/Sprites.meta
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Resource/Sprites/borderGrey32-4.png b/Runtime/InterfaceAttributeReflectionGenerator/Resources/Sprites/borderGrey32-4.png
similarity index 100%
rename from Runtime/InterfaceAttributeReflectionGenerator/Resource/Sprites/borderGrey32-4.png
rename to Runtime/InterfaceAttributeReflectionGenerator/Resources/Sprites/borderGrey32-4.png
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Resource/Sprites/borderGrey32-4.png.meta b/Runtime/InterfaceAttributeReflectionGenerator/Resources/Sprites/borderGrey32-4.png.meta
similarity index 100%
rename from Runtime/InterfaceAttributeReflectionGenerator/Resource/Sprites/borderGrey32-4.png.meta
rename to Runtime/InterfaceAttributeReflectionGenerator/Resources/Sprites/borderGrey32-4.png.meta
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/IXuiavrgAttribute.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/IXuiavrgAttribute.cs
new file mode 100644
index 0000000..44d9a08
--- /dev/null
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/IXuiavrgAttribute.cs
@@ -0,0 +1,7 @@
+namespace XericUI.ReflectionUIGenerator
+{
+ public interface IXuiavrgAttribute
+ {
+ public void BindProperty(XuiavrgInspectorProperty property);
+ }
+}
\ No newline at end of file
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/IXuiavrgAttribute.cs.meta b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/IXuiavrgAttribute.cs.meta
new file mode 100644
index 0000000..15b99d6
--- /dev/null
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/IXuiavrgAttribute.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 998589d7b3414ddd99b69cb128d7e052
+timeCreated: 1777014404
\ No newline at end of file
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrPropertyScriptableObject.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrPropertyScriptableObject.cs
new file mode 100644
index 0000000..36a81ba
--- /dev/null
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrPropertyScriptableObject.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+#if ODIN_INSPECTOR
+using Sirenix.OdinInspector;
+#endif
+using UnityEngine;
+using XericLibrary.Runtime.MacroLibrary;
+using Object = UnityEngine.Object;
+
+namespace XericUI.ReflectionUIGenerator
+{
+ ///
+ /// 属性映射器
+ ///
+ [Serializable]
+ [CreateAssetMenu(fileName = "Xeric UI avr Property", menuName = "Xeric Library/UI Action Vessel/Reflection UI Gen/UI avr Property", order = 10)]
+ public class XuiavrPropertyScriptableObject : ScriptableObject
+ {
+#if ODIN_INSPECTOR
+ [LabelText("属性类型")]
+ [ValueDropdown("AssemblyValueTypeNames")]
+#endif
+ public string valueType;
+#if ODIN_INSPECTOR
+ [LabelText("属性名称")]
+#endif
+ public string propertyName;
+#if ODIN_INSPECTOR
+ [LabelText("界面预制体")]
+#endif
+ public GameObject prefab;
+
+ ///
+ /// 属性类型
+ ///
+ public System.Type ValueType
+ {
+ get
+ {
+ if (_valueType != null)
+ return _valueType;
+ return _valueType = Type.GetType(valueType);
+ }
+ }
+ private System.Type _valueType;
+
+ ///
+ /// 属性类型名称枚举
+ ///
+ private IEnumerable AssemblyValueTypeNames
+ {
+ get
+ {
+ if (_assemblyValueTypeName != null)
+ return _assemblyValueTypeName;
+ _assemblyValueTypeName = new ValueDropdownList();
+
+ // foreach (var typeName in MacroReflection.GetAllAssignableTypeInAppDomainAssembly(
+ // typeof(float),
+ // typeof(string),
+ // typeof(bool),
+ // typeof(Enum),
+ // typeof(int)
+ // ).Select(a => a.FullName))
+ // {
+ // _assemblyValueTypeName.Add(typeName);
+ // }
+
+ _assemblyValueTypeName.AddRange(AllValueType.Select(a => new ValueDropdownItem(a.Name, a.FullName)));
+ return _assemblyValueTypeName;
+ }
+ }
+ private static ValueDropdownList _assemblyValueTypeName = null;
+
+ ///
+ /// 直接定义所有需要检查的类型
+ ///
+ public static IEnumerable AllValueType
+ {
+ get
+ {
+ yield return typeof(Enum);
+ yield return typeof(decimal);
+ yield return typeof(double);
+ yield return typeof(float);
+ yield return typeof(ulong);
+ yield return typeof(long);
+ yield return typeof(int);
+ yield return typeof(uint);
+ yield return typeof(short);
+ yield return typeof(ushort);
+ yield return typeof(byte);
+ yield return typeof(sbyte);
+ yield return typeof(string);
+ yield return typeof(char);
+ yield return typeof(bool);
+ }
+ }
+
+
+
+
+ }
+}
\ No newline at end of file
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrPropertyScriptableObject.cs.meta b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrPropertyScriptableObject.cs.meta
new file mode 100644
index 0000000..fbe1215
--- /dev/null
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrPropertyScriptableObject.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: be0acbdac8e549578dcccf8c076a5433
+timeCreated: 1776998687
\ No newline at end of file
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgAttribute.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgAttribute.cs
index d3972c6..80a349a 100644
--- a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgAttribute.cs
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgAttribute.cs
@@ -1,7 +1,78 @@
-namespace XericUI.ReflectionUIGenerator
+using System;
+
+namespace XericUI.ReflectionUIGenerator
{
- public class XuiavrgAttribute
+ ///
+ /// 反射属性标记
+ ///
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
+ public class XuiavrgAttribute : Attribute, IXuiavrgAttribute
{
-
+ #region 字段属性
+
+ public readonly string LabelName;
+ public readonly string UIPropertyName;
+ public readonly string UnitLabelName;
+ public readonly bool MustFillIn;
+ public readonly int InspectorOrder;
+ public readonly string GroupName;
+ public readonly string OnTriggerCall;
+ public readonly XuiavrgSize ArgumentSize;
+
+ ///
+ /// 标记属性
+ ///
+ /// 属性显示名称
+ /// 属性标记名(对应界面元素名称)
+ /// 属性显示单位名称
+ /// 是否标记为必填项目
+ /// 属性显示顺序
+ /// 属性组名称(可以是以/&\分割的路径)
+ /// 属性附加的动作,调用此内联反射调用的函数
+ /// 属性组名称(可以是以/&\分割的路径)
+ public XuiavrgAttribute(string labelName, string uiPropertyName, string unitLabelName, bool mustFillin,
+ int inspectorOrder = 0, string groupName = null, string onTriggerCall = "", XuiavrgSize size = XuiavrgSize.Normal)
+ {
+ LabelName = labelName;
+ UIPropertyName = uiPropertyName;
+ UnitLabelName = unitLabelName;
+ MustFillIn = mustFillin;
+ InspectorOrder = inspectorOrder;
+ GroupName = groupName;
+ OnTriggerCall = onTriggerCall;
+ ArgumentSize = size;
+ }
+
+ #endregion
+
+ #region 生成器
+
+ public void BindProperty(XuiavrgInspectorProperty property)
+ {
+ property.labelName = LabelName;
+ property.uiPropertyName = UIPropertyName;
+ property.unitLabelName = UnitLabelName;
+ property.mustFillIn = MustFillIn;
+ property.inspectorOrder = InspectorOrder;
+ property.groupName = GroupName;
+ property.onTriggerCall = OnTriggerCall;
+ property.argumentSize = ArgumentSize;
+ }
+
+ #endregion
+ }
+
+ ///
+ /// 属性尺寸
+ ///
+ public enum XuiavrgSize
+ {
+ None = 0,
+
+ Tiny = 1000 - 2,
+ Small = 1000 - 1,
+ Normal = 1000,
+ Big,
+ Large,
}
}
\ No newline at end of file
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgHideAttribute.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgHideAttribute.cs
new file mode 100644
index 0000000..b74ca34
--- /dev/null
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgHideAttribute.cs
@@ -0,0 +1,28 @@
+using System;
+using UnityEngine.Serialization;
+
+namespace XericUI.ReflectionUIGenerator
+{
+ ///
+ /// 隐藏标记
+ ///
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
+ public class XuiavrgHideAttribute : Attribute, IXuiavrgAttribute
+ {
+ public readonly bool Hide;
+
+ ///
+ /// 标记属性
+ ///
+ /// 隐藏属性
+ public XuiavrgHideAttribute(bool hideInInspector = true)
+ {
+ Hide = hideInInspector;
+ }
+
+ public void BindProperty(XuiavrgInspectorProperty property)
+ {
+ property.hideInInspector = Hide;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgHideAttribute.cs.meta b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgHideAttribute.cs.meta
new file mode 100644
index 0000000..8e36c83
--- /dev/null
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgHideAttribute.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 12f7aecaa5224304b1058ab9dc04a95f
+timeCreated: 1776995602
\ No newline at end of file
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorManager.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorManager.cs
new file mode 100644
index 0000000..d61fe21
--- /dev/null
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorManager.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Deconstruction.Type.Peculiarity;
+#if ODIN_INSPECTOR
+using Sirenix.OdinInspector;
+#endif
+using UnityEngine;
+using UnityEngine.Pool;
+
+namespace XericUI.ReflectionUIGenerator
+{
+ ///
+ /// 节点下生成反射属性管理器
+ ///
+ ///
+ /// 管理器需要挂载在unity节点中,管理器中指定的属性承载节点将用于生成属性内容。
+ ///
+ /// 为了准确生成界面属性,首先需要准备界面属性预制体。
+ /// 在包含界面交互元素的预制体跟目录上挂载 脚本,其将作为组件入口,管理所有的交互组件,必须在脚本中添加所有允许交互的元素。
+ /// (注:如果你没有odin插件,那么组件样式可能会与设计的不一致,请务必确保每个数组中只包含一个组件)
+ ///
+ /// 然后在工程中创建 对象,指定对应的数据类型,将刚刚创建的界面预制体拖入,这样就完成了两者的绑定。
+ /// 为了方便管理,再创建一个 对象,它可以成为一个组,快速管理和切换所需的数据集合。
+ ///
+ /// 接下来,在管理器中填入使用的 对象,然后调用 SchemaHydration 方法传入负载,界面顷刻生成。
+ ///
+ ///
+ public class XuiavrgInspectorManager : MonoBehaviour
+ {
+ public static Func CreatInspectorProperty = () => new XuiavrgInspectorProperty();
+ public static Action GetInspectorProperty = a => {};
+ public static Action ReleaseInspectorProperty = a => a.Clear();
+ public static Action DestoryInspectorProperty = a => {};
+ public static ObjectPool InspectorPropertyPool
+ = new ObjectPool(CreatInspectorProperty, GetInspectorProperty, ReleaseInspectorProperty, DestoryInspectorProperty);
+
+#if ODIN_INSPECTOR
+ [LabelText("预制体组")]
+#endif
+ public XuiavrgPropertyGroupScriptableObject propertyUIPrefabsGroup;
+#if ODIN_INSPECTOR
+ [LabelText("反射属性预览")]
+#endif
+ public List allProperty = new List();
+
+
+ ///
+ /// 装填数据负载
+ ///
+ /// 数据端对象
+#if ODIN_INSPECTOR
+ [Button]
+#endif
+ public void SchemaHydration(object payload)
+ {
+ // 清空环境和界面
+ allProperty.Clear();
+ InspectorPropertyPool.Clear();
+
+ if (!propertyUIPrefabsGroup)
+ {
+ Debug.LogError("未指定编组,无法生成界面");
+ return;
+ }
+
+ if (payload != null)
+ {
+ Debug.LogError("未指定有效负载,无法生成界面");
+ return;
+ }
+
+ // 从反射构建
+ var type = payload.GetType();
+ SchemaHydration(allProperty, type, payload);
+ }
+
+
+
+ ///
+ /// 状态数据负载
+ ///
+ /// 反射属性结合
+ /// 负载实例
+ /// 进行检查的负载类型
+ private static void SchemaHydration(List properties, object payload)
+ => SchemaHydration(properties, typeof(T), payload);
+
+ ///
+ /// 装填数据负载
+ ///
+ /// 反射属性集合
+ /// 进行检查的负载类型
+ /// 负载实例
+ private static void SchemaHydration(List properties, Type payloadType, object payload)
+ {
+ bool needSort = false;
+ foreach (var memberInfo in payloadType.GetRuntimeMemberInfo())
+ {
+ var mw = InspectorPropertyPool.Get();
+ // 绑定负载
+ mw.RegsiterDataValue(memberInfo, payload);
+ // 字段属性上的所有特性都进行标记
+ foreach (var memberAttribute in memberInfo.GetCustomAttributes()
+ .OfType())
+ {
+ memberAttribute.BindProperty(mw);
+ needSort |= mw.inspectorOrder != 0; // 如果有成员使用了order
+ }
+ properties.Add(mw);
+ }
+ // 排序
+ if (needSort)
+ properties.Sort((property1, property2) => property1.inspectorOrder.CompareTo(property2.inspectorOrder));
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgManager.cs.meta b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorManager.cs.meta
similarity index 100%
rename from Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgManager.cs.meta
rename to Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorManager.cs.meta
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorProperty.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorProperty.cs
new file mode 100644
index 0000000..972a807
--- /dev/null
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorProperty.cs
@@ -0,0 +1,142 @@
+using System;
+using System.Reflection;
+using UnityEngine.Serialization;
+
+namespace XericUI.ReflectionUIGenerator
+{
+ ///
+ /// 反射属性中间层
+ ///
+ [Serializable]
+ public class XuiavrgInspectorProperty
+ {
+ public object valueTarget;
+ public bool isProperty;
+ public PropertyInfo propertyInfo;
+ public FieldInfo fieldInfo;
+
+ public string labelName;
+ public string uiPropertyName;
+ public string unitLabelName;
+ public bool mustFillIn;
+ public int inspectorOrder;
+ public string groupName;
+ public string onTriggerCall;
+ public XuiavrgSize argumentSize;
+ public bool hideInInspector;
+
+
+ ///
+ /// 绑定到数据端
+ ///
+ ///
+ ///
+ public void RegsiterDataValue(MemberInfo memberInfo, object target)
+ {
+ switch (memberInfo)
+ {
+ case PropertyInfo propertyInfo:
+ RegsiterDataValue(propertyInfo, target);
+ break;
+ case FieldInfo fieldInfo:
+ RegsiterDataValue(fieldInfo, target);
+ break;
+ }
+ }
+
+ ///
+ /// 绑定到数据端
+ ///
+ ///
+ ///
+ public virtual void RegsiterDataValue(PropertyInfo memberInfo, object target)
+ {
+ valueTarget = target;
+ isProperty = true;
+ propertyInfo = memberInfo;
+ }
+
+ ///
+ /// 绑定到数据端
+ ///
+ ///
+ ///
+ public virtual void RegsiterDataValue(FieldInfo memberInfo, object target)
+ {
+ valueTarget = target;
+ isProperty = false;
+ fieldInfo = memberInfo;
+ }
+
+ ///
+ /// 绑定到界面端
+ ///
+ public virtual void RegsiterUIElement()
+ {
+
+ }
+
+
+ ///
+ /// 数据端值发生变更
+ ///
+ public void CallDataValueChange()
+ {
+
+ }
+
+ ///
+ /// 界面端数据发生变更
+ ///
+ public void CallUIValueChange()
+ {
+
+ }
+
+ ///
+ /// 从数据端获取值
+ ///
+ ///
+ public object GetValueFromTargetMember()
+ {
+ if (isProperty)
+ return propertyInfo.GetValue(valueTarget);
+ else
+ return fieldInfo.GetValue(valueTarget);
+ }
+
+ ///
+ /// 设置值到数据端
+ ///
+ ///
+ public void SetValueToTargetMember(object value)
+ {
+ if (isProperty)
+ propertyInfo.SetValue(valueTarget, value);
+ else
+ fieldInfo.SetValue(valueTarget, value);
+ }
+
+ ///
+ /// 从界面端获取值
+ ///
+ ///
+ public object GetValueFormUIElement()
+ {
+ return null;
+ }
+
+ ///
+ /// 设置值到界面端
+ ///
+ ///
+ public void SetValueToUIElement(object value)
+ {
+
+ }
+
+ public void Clear()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorProperty.cs.meta b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorProperty.cs.meta
new file mode 100644
index 0000000..a6c88e1
--- /dev/null
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorProperty.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 5d82ae110adb48b397c09939694cc3b2
+timeCreated: 1777011022
\ No newline at end of file
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgLocator.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgLocator.cs
new file mode 100644
index 0000000..b4f1b7b
--- /dev/null
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgLocator.cs
@@ -0,0 +1,305 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Sirenix.OdinInspector;
+using UnityEngine;
+using UnityEngine.Serialization;
+
+namespace XericUI.ReflectionUIGenerator
+{
+ ///
+ /// ui·´ÉäÊôÐԶ¨λÆ÷£¬·ÅÔÚUI¶ÔÏóµĸù½ڵãÉϣ¬É趨ºýÓÏÂÀ´µÄĿ±꼴¿É
+ ///
+ public class XuiavrgLocator : MonoBehaviour
+ {
+ public delegate void AnyTrigger(LocatorProperty locator, object value, int selectStart, int selectEnd);
+
+#if ODIN_INSPECTOR
+ [LabelText("ӳÉä×é¼þ")]
+#endif
+ public List Properties;
+
+ [Serializable]
+ public class LocatorProperty
+ {
+#if ODIN_INSPECTOR
+ [LabelText("×é¼þ±êʶÃû")]
+#endif
+ [Tooltip("½¨ÒéʹÓà name, label, unit, sign, input, output, button, slider, edit, select µȼòµ¥Ò®µÄÃû³ƽøÐбê¼Ç")]
+ public string propertyName;
+#if ODIN_INSPECTOR
+ [LabelText("×é¼þÀàÐÍ")]
+#endif
+ public UIElementClassify classify;
+#if dUI_TextMeshPro
+#if ODIN_INSPECTOR
+ [ShowIf("classify", UIElementClassify.TMPText)]
+#endif
+ public TMPro.TMP_Text TMPText;
+#if ODIN_INSPECTOR
+ [ShowIf("classify", UIElementClassify.TMPInputField)]
+#endif
+ public TMPro.TMP_InputField TMPInputField;
+#endif
+#if ODIN_INSPECTOR
+ [ShowIf("classify", UIElementClassify.UIText)]
+#endif
+ public UnityEngine.UI.Text UIText;
+#if ODIN_INSPECTOR
+ [ShowIf("classify", UIElementClassify.UIInputField)]
+#endif
+ public UnityEngine.UI.InputField UIInputField;
+#if ODIN_INSPECTOR
+ [ShowIf("classify", UIElementClassify.UIToggle)]
+#endif
+ public UnityEngine.UI.Toggle UIToggle;
+#if ODIN_INSPECTOR
+ [ShowIf("classify", UIElementClassify.UIButton)]
+#endif
+ public UnityEngine.UI.Button UIButton;
+#if ODIN_INSPECTOR
+ [ShowIf("classify", UIElementClassify.UISlider)]
+#endif
+ public UnityEngine.UI.Slider UISlider;
+#if ODIN_INSPECTOR
+ [ShowIf("classify", UIElementClassify.UIDropdown)]
+#endif
+ public UnityEngine.UI.Dropdown UIDropdown;
+
+#if ODIN_INSPECTOR
+ [ShowIf("classify", UIElementClassify.TMPInputField)]
+#endif
+ public TMPInputTriggerEvent TMPInputTriggerOnEventType;
+#if ODIN_INSPECTOR
+ [ShowIf("classify", UIElementClassify.UIInputField)]
+#endif
+ public UIInputTriggerEvent UIInputTriggerOnEventType;
+
+ ///
+ /// ֧³ֵÄ×é¼þÀàÐÍ
+ ///
+ public enum UIElementClassify
+ {
+ None,
+#if dUI_TextMeshPro
+ TMPText,
+ TMPInputField,
+#endif
+ UIText,
+ UIInputField,
+ UIToggle,
+ UIButton,
+ UISlider,
+ UIDropdown,
+ }
+
+ [Flags]
+ public enum TMPInputTriggerEvent
+ {
+ none,
+ onEndEdit = 1 << 1,
+ onSubmit = 1 << 2,
+ onSelect = 1 << 3,
+ onDeselect = 1 << 4,
+ onTextSelection = 1 << 5,
+ onEndTextSelection = 1 << 6,
+ onValueChanged = 1 << 7,
+ onTouchScreenKeyboardStatusChanged = 1 << 8,
+ }
+
+ public enum UIInputTriggerEvent
+ {
+ none,
+ onEndEdit,
+ onSubmit,
+ onValueChanged,
+ }
+
+ ///
+ /// »ñȡֵ
+ ///
+ ///
+ ///
+ public object GetValue()
+ {
+ switch (classify)
+ {
+#if dUI_TextMeshPro
+ case UIElementClassify.TMPText:
+ return TMPText.text;
+ case UIElementClassify.TMPInputField:
+ return TMPInputField.text;
+#endif
+ case UIElementClassify.UIText:
+ return UIText.text;
+ case UIElementClassify.UIInputField:
+ return UIInputField.text;
+ case UIElementClassify.UIToggle:
+ return UIToggle.isOn;
+ case UIElementClassify.UIButton:
+ return false;
+ case UIElementClassify.UISlider:
+ return UISlider.value;
+ case UIElementClassify.UIDropdown:
+ return UIDropdown.value;
+ default:
+ return null;
+ }
+ }
+
+ ///
+ /// ÉèÖÃֵ
+ ///
+ ///
+ ///
+ public void SetValue(object value)
+ {
+ switch (classify)
+ {
+#if dUI_TextMeshPro
+ case UIElementClassify.TMPText:
+ TMPText.text = value.ToString();
+ break;
+ case UIElementClassify.TMPInputField:
+ TMPInputField.text = value.ToString();
+ break;
+#endif
+ case UIElementClassify.UIText:
+ UIText.text = value.ToString();
+ break;
+ case UIElementClassify.UIInputField:
+ UIInputField.text = value.ToString();
+ break;
+ case UIElementClassify.UIToggle:
+ UIToggle.isOn = Convert.ToBoolean(value);
+ break;
+ case UIElementClassify.UIButton:
+ // UIButton do nothing
+ break;
+ case UIElementClassify.UISlider:
+ UISlider.value = Convert.ToSingle(value);
+ break;
+ case UIElementClassify.UIDropdown:
+ UIDropdown.value = Convert.ToInt32(value);
+ break;
+ default:
+ break;
+ }
+ }
+
+ ///
+ /// ui´¥·¢Ê¼þ
+ ///
+ public event AnyTrigger OnUITrigger
+ {
+ add
+ {
+ switch (classify)
+ {
+#if dUI_TextMeshPro
+ case UIElementClassify.TMPInputField:
+ switch (TMPInputTriggerOnEventType)
+ {
+ case TMPInputTriggerEvent.onEndEdit:
+ TMPInputField.onEndEdit.AddListener(a => value?.Invoke(this, a, 0, 0));
+ break;
+ case TMPInputTriggerEvent.onSubmit:
+ TMPInputField.onSubmit.AddListener(a => value?.Invoke(this, a, 0, 0));
+ break;
+ case TMPInputTriggerEvent.onSelect:
+ TMPInputField.onSelect.AddListener(a => value?.Invoke(this, a, 0, 0));
+ break;
+ case TMPInputTriggerEvent.onDeselect:
+ TMPInputField.onDeselect.AddListener(a => value?.Invoke(this, a, 0, 0));
+ break;
+ case TMPInputTriggerEvent.onTextSelection:
+ TMPInputField.onTextSelection.AddListener((content, start, end) =>
+ value?.Invoke(this, content, start, end));
+ break;
+ case TMPInputTriggerEvent.onEndTextSelection:
+ TMPInputField.onEndTextSelection.AddListener((content, start, end) =>
+ value?.Invoke(this, content, start, end));
+ break;
+ case TMPInputTriggerEvent.onValueChanged:
+ TMPInputField.onValueChanged.AddListener(a => value?.Invoke(this, a, 0, 0));
+ break;
+ case TMPInputTriggerEvent.onTouchScreenKeyboardStatusChanged:
+ TMPInputField.onTouchScreenKeyboardStatusChanged.AddListener(a =>
+ value?.Invoke(this, a, 0, 0));
+ break;
+ default:
+ break;
+ }
+
+ break;
+#endif
+ case UIElementClassify.UIInputField:
+ switch (UIInputTriggerOnEventType)
+ {
+ case UIInputTriggerEvent.onEndEdit:
+ UIInputField.onEndEdit.AddListener(a => value?.Invoke(this, a, 0, 0));
+ break;
+ case UIInputTriggerEvent.onSubmit:
+ UIInputField.onSubmit.AddListener(a => value?.Invoke(this, a, 0, 0));
+ break;
+ case UIInputTriggerEvent.onValueChanged:
+ UIInputField.onValueChanged.AddListener(a => value?.Invoke(this, a, 0, 0));
+ break;
+ default: break;
+ }
+
+ break;
+ case UIElementClassify.UIToggle:
+ UIToggle.onValueChanged.AddListener(a => value?.Invoke(this, value, 0, 0));
+ break;
+ case UIElementClassify.UIButton:
+ UIButton.onClick.AddListener(() => value?.Invoke(this, true, 0, 0));
+ break;
+ case UIElementClassify.UISlider:
+ UISlider.onValueChanged.AddListener(a => value?.Invoke(this, a, 0, 0));
+ break;
+ case UIElementClassify.UIDropdown:
+ UIDropdown.onValueChanged.AddListener(a => value?.Invoke(this, a, 0, 0));
+ break;
+ default:
+ break;
+ }
+ }
+ remove { Debug.Log("ÈÎÒⴥ·¢Æ÷ΨжÔØÌض¨Ê¼þ"); }
+ }
+
+ ///
+ /// Çå¿Õui´¥·¢Ê¼þ
+ ///
+ public void ClearTriggerEvent()
+ {
+ if (TMPInputField)
+ {
+ TMPInputField.onEndEdit.RemoveAllListeners();
+ TMPInputField.onSubmit.RemoveAllListeners();
+ TMPInputField.onSelect.RemoveAllListeners();
+ TMPInputField.onDeselect.RemoveAllListeners();
+ TMPInputField.onTextSelection.RemoveAllListeners();
+ TMPInputField.onEndTextSelection.RemoveAllListeners();
+ TMPInputField.onValueChanged.RemoveAllListeners();
+ TMPInputField.onTouchScreenKeyboardStatusChanged.RemoveAllListeners();
+ }
+
+ if (UIInputField)
+ {
+ UIInputField.onEndEdit.RemoveAllListeners();
+ UIInputField.onSubmit.RemoveAllListeners();
+ UIInputField.onValueChanged.RemoveAllListeners();
+ }
+
+ UIToggle?.onValueChanged.RemoveAllListeners();
+ UIButton?.onClick.RemoveAllListeners();
+ UISlider?.onValueChanged.RemoveAllListeners();
+ UIDropdown?.onValueChanged.RemoveAllListeners();
+ }
+ }
+
+ // todo ʹÓÃÃû³ƣ¬ÀàÐÍɸѡµõ½×é¼þ
+ // todo ¸ù¾ÝÃû³Æ×齨×ֵäÊ÷¼ÓËٲéÕң¨»òÐí²»Óã©
+ }
+}
\ No newline at end of file
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgPooledLocator.cs.meta b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgLocator.cs.meta
similarity index 100%
rename from Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgPooledLocator.cs.meta
rename to Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgLocator.cs.meta
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgManager.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgManager.cs
deleted file mode 100644
index 3eb3be2..0000000
--- a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgManager.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using Deconstruction.Type.Peculiarity;
-using UnityEngine;
-
-namespace XericUI.ReflectionUIGenerator
-{
- ///
- /// 节点下生成反射属性管理器
- ///
- public class XuiavrgManager
- {
-
- ///
- /// 装填数据负载
- ///
- ///
- public void PerformSchemaDrivenHydration(object payload)
- {
- var type = payload.GetType();
-
- var attributes = type.GetCustomAttributes(true);
- foreach (var attribute in attributes)
- {
- if (attribute is not XuiavrgAttribute xuiavrgAttribute)
- continue;
-
-
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgPooledLocator.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgPooledLocator.cs
deleted file mode 100644
index 5ced82a..0000000
--- a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgPooledLocator.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System.Collections;
-using System.Collections.Generic;
-using UnityEngine;
-
-namespace XericUI.ReflectionUIGenerator
-{
- ///
- /// ui·´ÉäÊôÐԶ¨λÆ÷£¬·ÅÔڳضÔÏóµĸù½ڵãÉϣ¬É趨ºýÓÏÂÀ´µÄĿ±꼴¿É
- ///
- public class XuiavrgPooledLocator : MonoBehaviour
- {
-
- }
-}
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgPropertyGroupScriptableObject.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgPropertyGroupScriptableObject.cs
new file mode 100644
index 0000000..b4e9228
--- /dev/null
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgPropertyGroupScriptableObject.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace XericUI.ReflectionUIGenerator
+{
+ ///
+ /// 界面属性编组
+ ///
+ [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
+ {
+ public List propertys = new List();
+
+ public IEnumerator 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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgPropertyGroupScriptableObject.cs.meta b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgPropertyGroupScriptableObject.cs.meta
new file mode 100644
index 0000000..5f0eb3a
--- /dev/null
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgPropertyGroupScriptableObject.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: bcd1c64483d2457ab9143f086dff511d
+timeCreated: 1777024131
\ No newline at end of file
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgUtilities.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgUtilities.cs
index e6d758f..64376f4 100644
--- a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgUtilities.cs
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgUtilities.cs
@@ -1,7 +1,22 @@
-namespace XericUI.ReflectionUIGenerator
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace XericUI.ReflectionUIGenerator
{
public static class XuiavrgUtilities
{
-
+ ///
+ /// 获取所有运行时成员(字段和属性)
+ ///
+ ///
+ ///
+ public static IEnumerable GetRuntimeMemberInfo(this Type type)
+ {
+ foreach (var field in type.GetRuntimeFields())
+ yield return field;
+ foreach (var property in type.GetRuntimeProperties())
+ yield return property;
+ }
}
}
\ No newline at end of file
diff --git a/Runtime/OverrideLayout/XericScrollRect.cs b/Runtime/OverrideLayout/XericScrollRect.cs
index 4228461..6dd1a33 100644
--- a/Runtime/OverrideLayout/XericScrollRect.cs
+++ b/Runtime/OverrideLayout/XericScrollRect.cs
@@ -33,11 +33,11 @@ namespace XericUI.OverrideLayout
[Tooltip("容器预加载像素范围")] [SerializeField]
protected float m_preloadMargin = 200f;
- [Tooltip("容器加载响应可被察觉的变化长度")] [SerializeField]
+ [Tooltip("容器加载响应可被察觉的变化长度(建议设置为子项的二维最小的尺寸)")] [SerializeField]
protected float m_discernibleDistance = 10f;
[Tooltip("自动剔除更新速率,当设定趋近零时,实际上是期望每帧执行更新")] [SerializeField]
- protected float m_AAMVUpdateRate = .5f;
+ protected float m_AAMVUpdateRate = .1f;
// grid布局组件
[SerializeField] protected Vector2 m_cellSize = new Vector2(100, 100);
@@ -261,7 +261,7 @@ namespace XericUI.OverrideLayout
// 扩展可见区域边界
var visibleMin = viewportRect.min - new Vector2(m_preloadMargin, m_preloadMargin);
- var visibleMax = viewportRect.max + new Vector2(m_preloadMargin, m_preloadMargin);
+ var visibleMax = viewportRect.max + new Vector2(m_preloadMargin, -m_preloadMargin);
// 获取当前滚动归一化位置
// var scrollPos = new Vector2(
@@ -397,22 +397,34 @@ namespace XericUI.OverrideLayout
private void RefreshContentSizeByChildrenLayouts(List layoutItems)
{
+ if (layoutItems.Count == 0) return;
+
var first = layoutItems[0];
var last = layoutItems[^1];
var size = first.position - last.position;
size = size.Abs();
- var spacing = new Vector2(GridLayoutCalculator.Grid.x * m_spacing.x, GridLayoutCalculator.Grid.y * m_spacing.y);
+
+ // 计算实际使用的行列数
+ int maxRow = 0;
+ int maxColumn = 0;
+ foreach (var item in layoutItems)
+ {
+ maxRow = Mathf.Max(maxRow, item.rowIndex);
+ maxColumn = Mathf.Max(maxColumn, item.columnIndex);
+ }
+ int actualCellCountX = maxColumn + 1;
+ int actualCellCountY = maxRow + 1;
+
+ var spacing = new Vector2((actualCellCountX - 1) * m_spacing.x, (actualCellCountY - 1) * m_spacing.y);
switch (m_startAxis)
{
case GridLayoutGroup.Axis.Horizontal:
- var ySpacing = GridLayoutCalculator.Grid.y * m_spacing.y;
size.x = Mathf.Max(size.x, viewport.rect.width);
- size.y = Mathf.Max(size.y + spacing.y, m_cellSize.y);
+ size.y = Mathf.Max(size.y + m_spacing.y, m_cellSize.y);
break;
case GridLayoutGroup.Axis.Vertical:
- var xSpacing = GridLayoutCalculator.Grid.x * m_spacing.x;
- size.x = Mathf.Max(size.x + spacing.x, m_cellSize.x);
+ size.x = Mathf.Max(size.x + m_spacing.x, m_cellSize.x);
size.y = Mathf.Max(size.y, viewport.rect.height);
break;
}
@@ -454,7 +466,17 @@ namespace XericUI.OverrideLayout
}
private List GetChildrenLayout(int childrenCount)
- => GridLayoutCalculator.CalculateGridLayout(
+ {
+ // 根据约束类型设置合适的 constraintCount
+ int constraintCount = 0;
+ if (m_constraint == GridLayoutGroup.Constraint.FixedColumnCount || m_constraint == GridLayoutGroup.Constraint.FixedRowCount)
+ {
+ // 这里可以根据实际需求设置合适的约束数量
+ // 暂时使用一个默认值,实际项目中可能需要从外部传入或通过其他方式计算
+ constraintCount = 3;
+ }
+
+ return GridLayoutCalculator.CalculateGridLayout(
_layoutItems,
childCount: childrenCount,
containerSize: ContextSize,
@@ -464,9 +486,10 @@ namespace XericUI.OverrideLayout
startCorner: m_startCorner,
startAxis: m_startAxis,
constraint: m_constraint,
- constraintCount: 0,
+ constraintCount: constraintCount,
childAlignment: m_childAlignment
);
+ }
public void RefreshChildrenLayout()
{